mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 08:08:04 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67b19ae733 | ||
|
|
c4c812c154 | ||
|
|
388e236360 | ||
|
|
f2c8ddbbe3 | ||
|
|
d1d4388201 | ||
|
|
6ffed14b9c | ||
|
|
7f6d0b8709 | ||
|
|
d7b1919b29 | ||
|
|
f86e6f8eb0 | ||
|
|
7e780e57d4 | ||
|
|
9a5a13854d | ||
|
|
a795017416 | ||
|
|
8e3b361aeb | ||
|
|
f9dd5683a4 | ||
|
|
e38a6e7996 | ||
|
|
ddfaf3fee0 | ||
|
|
0dbf01bf1d | ||
|
|
3a599bfbe1 | ||
|
|
89fc95fefd | ||
|
|
8e37ee2598 | ||
|
|
d9b4f647d8 | ||
|
|
0dde3a0e70 | ||
|
|
32643e9fa7 | ||
|
|
0a92c78035 | ||
|
|
118db71121 | ||
|
|
a0410f0170 | ||
|
|
d44a7dc603 | ||
|
|
2ba6b0158f | ||
|
|
f3effcb703 | ||
|
|
03b476f943 | ||
|
|
8b3e368e9a | ||
|
|
df6b384e31 | ||
|
|
280bdec817 | ||
|
|
2c5e7ec547 | ||
|
|
fdcb8b2f7e | ||
|
|
04c6bc478e | ||
|
|
cc2c1893c5 |
No files matched your search
@@ -1,6 +1,10 @@
|
||||
# Run this command to always ignore formatting commits in git blame
|
||||
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
|
||||
# Upgraded clang-format to 19.0.0git
|
||||
89fc95fefd40413706ff1bdaac2e8d98b328dbf1
|
||||
# vim c++ filetype in modelines
|
||||
04c6bc478e082263d67c41bedbd033dde2d429eb
|
||||
# Ran clang-format
|
||||
f032b5570b4cd87c6bb4abb54c0b98e69c939955
|
||||
# Applied clang-format update to repo
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Low Severity Bugs
|
||||
description: Used to report low severity bugs in cosmopolitan (e.g. cosmetic issues, non critical UI glitches)
|
||||
title: "Bug: "
|
||||
labels: ["bug", "low severity"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Please include information about your system, the steps to reproduce the bug,
|
||||
and the version of cosmopolitan that you are using.
|
||||
If possible, please provide a minimal code example that reproduces the bug.
|
||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. [email protected]
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running? (use `--version` to get a version string)
|
||||
placeholder: "cosmocc (GCC) 12.3.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: What operating system are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- Mac
|
||||
- Windows
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- BIOS
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Medium Severity Bug
|
||||
description: Used to report medium severity bugs in cosmopolitan (e.g. Malfunctioning Features but generally still useable)
|
||||
title: "Bug: "
|
||||
labels: ["bug", "medium severity"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Please include information about your system, the steps to reproduce the bug,
|
||||
and the version of cosmopolitan that you are using.
|
||||
If possible, please provide a minimal code example that reproduces the bug.
|
||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. [email protected]
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running? (use `--version` to get a version string)
|
||||
placeholder: "cosmocc (GCC) 12.3.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: What operating system are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- Mac
|
||||
- Windows
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- BIOS
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,59 @@
|
||||
name: High Severity Bug
|
||||
description: Used to report high severity bugs in cosmopolitan (e.g. Malfunctioning features hindering important common workflow)
|
||||
title: "Bug: "
|
||||
labels: ["bug", "high severity"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Please include information about your system, the steps to reproduce the bug,
|
||||
and the version of cosmopolitan that you are using.
|
||||
If possible, please provide a minimal code example that reproduces the bug.
|
||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. [email protected]
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running? (use `--version` to get a version string)
|
||||
placeholder: "cosmocc (GCC) 12.3.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: What operating system are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- Mac
|
||||
- Windows
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- BIOS
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Critical Severity Bug
|
||||
description: Used to report critical severity bugs in cosmopolitan (e.g. Crashing, Corrupted, Dataloss)
|
||||
title: "Bug: "
|
||||
labels: ["bug", "critical severity"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Please include information about your system, the steps to reproduce the bug,
|
||||
and the version of cosmopolitan that you are using.
|
||||
If possible, please provide a minimal code example that reproduces the bug.
|
||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
label: Contact Details
|
||||
description: How can we get in touch with you if we need more info?
|
||||
placeholder: ex. [email protected]
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running? (use `--version` to get a version string)
|
||||
placeholder: "cosmocc (GCC) 12.3.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: operating-system
|
||||
attributes:
|
||||
label: What operating system are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Linux
|
||||
- Mac
|
||||
- Windows
|
||||
- FreeBSD
|
||||
- OpenBSD
|
||||
- NetBSD
|
||||
- BIOS
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,51 @@
|
||||
name: Enhancement template
|
||||
description: Used to request enhancements for cosmopolitan
|
||||
title: "Feature Request: "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
[Please post your idea first in Discussion if there is not yet a consensus for this enhancement request. This will help to keep this issue tracker focused on enhancements that the community has agreed needs to be implemented.](https://github.com/jart/cosmopolitan/discussions/categories/ideas)
|
||||
|
||||
- type: checkboxes
|
||||
id: prerequisites
|
||||
attributes:
|
||||
label: Prerequisites
|
||||
description: Please confirm the following before submitting your enhancement request.
|
||||
options:
|
||||
- label: I am running the latest code. Mention the version if possible as well.
|
||||
required: true
|
||||
- label: I carefully followed the [README.md](https://github.com/jart/cosmopolitan/blob/master/README.md).
|
||||
required: true
|
||||
- label: I searched using keywords relevant to my issue to make sure that I am creating a new issue that is not already open (or closed).
|
||||
required: true
|
||||
- label: I reviewed the [Discussions](https://github.com/jart/cosmopolitan/discussions), and have a new and useful enhancement to share.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature Description
|
||||
description: Please provide a detailed written description of what you were trying to do, and what you expected `cosmopolitan` to do as an enhancement.
|
||||
placeholder: Detailed description of the enhancement
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: motivation
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: Please provide a detailed written description of reasons why this feature is necessary and how it is useful to `cosmopolitan` users.
|
||||
placeholder: Explanation of why this feature is needed and its benefits
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: possible-implementation
|
||||
attributes:
|
||||
label: Possible Implementation
|
||||
description: If you have an idea as to how it can be implemented, please write a detailed description. Feel free to give links to external sources or share visuals that might be helpful to understand the details better.
|
||||
placeholder: Detailed description of potential implementation
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,52 @@
|
||||
name: Research
|
||||
description: Track new technical research area
|
||||
title: "Research: "
|
||||
labels: ["research"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Don't forget to check for any [duplicate research issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3A%22research+%F0%9F%94%AC%22)
|
||||
|
||||
- type: checkboxes
|
||||
id: research-stage
|
||||
attributes:
|
||||
label: Research Stage
|
||||
description: Track general state of this research ticket
|
||||
options:
|
||||
- label: Background Research (Let's try to avoid reinventing the wheel)
|
||||
- label: Hypothesis Formed (How do you think this will work and it's effect?)
|
||||
- label: Strategy / Implementation Forming
|
||||
- label: Analysis of results
|
||||
- label: Debrief / Documentation (So people in the future can learn from us)
|
||||
|
||||
- type: textarea
|
||||
id: background
|
||||
attributes:
|
||||
label: Previous existing literature and research
|
||||
description: Whats the current state of the art and whats the motivation for this research?
|
||||
|
||||
- type: textarea
|
||||
id: hypothesis
|
||||
attributes:
|
||||
label: Hypothesis
|
||||
description: How do you think this will work and it's effect?
|
||||
|
||||
- type: textarea
|
||||
id: implementation
|
||||
attributes:
|
||||
label: Implementation
|
||||
description: Got an approach? e.g. a PR ready to go?
|
||||
|
||||
- type: textarea
|
||||
id: analysis
|
||||
attributes:
|
||||
label: Analysis
|
||||
description: How does the proposed implementation behave?
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Refactor (Maintainers)
|
||||
description: Used to track refactoring opportunities
|
||||
title: "Refactor: "
|
||||
labels: ["refactor"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Don't forget to [check for existing refactor issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3Arefactoring) in case it's already covered.
|
||||
Also you may want to check [Pull request refactor label as well](https://github.com/jart/cosmopolitan/pulls?q=is%3Aopen+is%3Apr+label%3Arefactoring) for duplicates too.
|
||||
|
||||
- type: textarea
|
||||
id: background-description
|
||||
attributes:
|
||||
label: Background Description
|
||||
description: Please provide a detailed written description of the pain points you are trying to solve.
|
||||
placeholder: Detailed description behind your motivation to request refactor
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: possible-approaches
|
||||
attributes:
|
||||
label: Possible Refactor Approaches
|
||||
description: If you have some idea of possible approaches to solve this problem. You may want to make it a todo list.
|
||||
placeholder: Your idea of possible refactoring opportunity/approaches
|
||||
validations:
|
||||
required: false
|
||||
@@ -0,0 +1,15 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: FAQ
|
||||
url: https://github.com/jart/cosmopolitan/wiki/FAQ
|
||||
about: Is your question a common one? You may want to check here first.
|
||||
- name: Got an idea?
|
||||
url: https://github.com/jart/cosmopolitan/discussions/categories/ideas
|
||||
about: Pop it there. It may then become an enhancement ticket.
|
||||
- name: Got a question?
|
||||
url: https://github.com/jart/cosmopolitan/discussions/categories/q-a
|
||||
about: Ask a question there!
|
||||
- name: Want to contribute?
|
||||
url: https://github.com/jart/cosmopolitan/wiki/contribute
|
||||
about: Head to the contribution guide page of the wiki for areas you can help with
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# https://github.com/actions/labeler
|
||||
|
||||
documentation:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- README.md
|
||||
- LICENSE
|
||||
- CONTRIBUTING.md
|
||||
- libc/README.md
|
||||
- tool/cosmocc/README.md
|
||||
- third_party/getopt/README.txt
|
||||
build:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- build/**
|
||||
- Makefile
|
||||
- '*/*.mk'
|
||||
examples:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: examples/**
|
||||
devops:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- .github/**
|
||||
- .clang-format
|
||||
dsp:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- dsp/**
|
||||
ape:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- ape/**
|
||||
libc:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- libc/**
|
||||
net:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- net/**
|
||||
third_party:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- third_party/**
|
||||
tool:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- tool/**
|
||||
@@ -0,0 +1,17 @@
|
||||
name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: "jart/cosmopolitan"
|
||||
- uses: actions/labeler@v5
|
||||
with:
|
||||
configuration-path: '.github/labeler.yml'
|
||||
@@ -162,7 +162,6 @@ o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/thread/tls.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
libc/nexgen32e/uart.internal.h \
|
||||
@@ -189,7 +188,6 @@ o/$(MODE)/ape/ape-copy-self.o: \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/thread/tls.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
libc/nexgen32e/uart.internal.h \
|
||||
|
||||
+6
-1
@@ -1,6 +1,7 @@
|
||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
ENTRY(_start)
|
||||
@@ -285,9 +286,13 @@ SECTIONS {
|
||||
|
||||
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
|
||||
ape_stack_align = DEFINED(ape_stack_align) ? ape_stack_align : 16;
|
||||
ape_stack_align = DEFINED(ape_stack_align) ? MAX(ape_stack_align, 16) : 16;
|
||||
ape_stack_prot = PROT_READ | PROT_WRITE;
|
||||
ape_stack_round = -ape_stack_align;
|
||||
|
||||
ASSERT(ape_stack_align < 1048576, "stack align too big");
|
||||
ASSERT(!(ape_stack_align & (ape_stack_align - 1)), "stack align must be two power");
|
||||
|
||||
_tls_size = _tbss_end - _tdata_start;
|
||||
_tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
|
||||
+4
-1
@@ -588,9 +588,12 @@ ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
||||
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
|
||||
ape_stack_filesz = 0;
|
||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
|
||||
ape_stack_align = DEFINED(ape_stack_align) ? ape_stack_align : 16;
|
||||
ape_stack_align = DEFINED(ape_stack_align) ? MAX(ape_stack_align, 16) : 16;
|
||||
ape_stack_round = -ape_stack_align;
|
||||
|
||||
ASSERT(ape_stack_align < 1048576, "stack align too big");
|
||||
ASSERT(!(ape_stack_align & (ape_stack_align - 1)), "stack align must be two power");
|
||||
|
||||
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
|
||||
ape_note_filesz = ape_note_end - ape_note;
|
||||
ape_note_memsz = ape_note_filesz;
|
||||
|
||||
@@ -84,9 +84,10 @@
|
||||
/* clang-format on */
|
||||
#elif defined(__LINKER__)
|
||||
|
||||
#define BCX_NIBBLE(X) ((((X)&0xf) > 0x9) ? ((X)&0xf) + 0x37 : ((X)&0xf) + 0x30)
|
||||
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
||||
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||
#define BCX_NIBBLE(X) \
|
||||
((((X) & 0xf) > 0x9) ? ((X) & 0xf) + 0x37 : ((X) & 0xf) + 0x30)
|
||||
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
||||
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||
#define BCXSTUB(SYM, X) \
|
||||
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
|
||||
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
|
||||
@@ -98,12 +99,12 @@
|
||||
*
|
||||
* <p>This allows linker scripts to generate printf commands.
|
||||
*/
|
||||
#define BCO_OCTET(X) (((X)&0x7) + 0x30)
|
||||
#define BCO_OCTET(X) (((X) & 0x7) + 0x30)
|
||||
#define BCOB_UNIT(X) \
|
||||
((BCO_OCTET((X) >> 0) << 24) | (BCO_OCTET((X) >> 3) << 16) | \
|
||||
(BCO_OCTET(((X)&0xff) >> 6) << 8) | 0x5c)
|
||||
(BCO_OCTET(((X) & 0xff) >> 6) << 8) | 0x5c)
|
||||
|
||||
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I)*8)))
|
||||
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I) * 8)))
|
||||
#define PFSTUB2(SYM, X) \
|
||||
HIDDEN(SYM = (X)); \
|
||||
PFBYTE(SYM, X, 0); \
|
||||
@@ -132,7 +133,7 @@
|
||||
#define SHSTUB2(SYM, X) \
|
||||
HIDDEN(SYM##_bcs0 = BCD_LEFT(X)); \
|
||||
HIDDEN(SYM##_bcs1 = BCD_RIGHT(X))
|
||||
#define BCD_SMEAR(X) ((X) + (X)*10000)
|
||||
#define BCD_SMEAR(X) ((X) + (X) * 10000)
|
||||
#define BCD_LEFT(X) \
|
||||
(((X)) < 10000 ? BCD_RIGHT(BCD_SMEAR(X)) | 0x10 \
|
||||
: (X) < 100000 ? BCD_RIGHT(BCD_SMEAR((X) / 10)) \
|
||||
|
||||
+2
-24
@@ -127,32 +127,10 @@ TARGET_ARCH ?= -msse3
|
||||
PYFLAGS += -O1
|
||||
endif
|
||||
|
||||
# Asan Mode
|
||||
#
|
||||
# Safer binaries good for backend production serving.
|
||||
#
|
||||
# - `make MODE=asan`
|
||||
# - Memory safety
|
||||
# - Production worthy
|
||||
# - Backtraces
|
||||
# - Debuggability
|
||||
# - Larger binaries
|
||||
#
|
||||
ifeq ($(MODE), asan)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -D__SANITIZE_ADDRESS__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
|
||||
CONFIG_COPTS += -fsanitize=address
|
||||
TARGET_ARCH ?= -msse3
|
||||
QUOTA ?= -C64 -L300
|
||||
endif
|
||||
|
||||
# Debug Mode
|
||||
#
|
||||
# - `make MODE=dbg`
|
||||
# - Backtraces
|
||||
# - Enables asan
|
||||
# - Enables ubsan
|
||||
# - Stack canaries
|
||||
# - No optimization
|
||||
@@ -161,9 +139,9 @@ endif
|
||||
ifeq ($(MODE), dbg)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__ -D__SANITIZE_UNDEFINED__
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
|
||||
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
|
||||
CONFIG_COPTS += -fsanitize=undefined
|
||||
TARGET_ARCH ?= -msse3
|
||||
OVERRIDE_CCFLAGS += -fno-pie
|
||||
QUOTA ?= -C64 -L300
|
||||
|
||||
@@ -64,9 +64,6 @@ BACKTRACES = \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
SANITIZER = \
|
||||
-fsanitize=address
|
||||
|
||||
NO_MAGIC = \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ This package provides an STL alternative that's designed to:
|
||||
|
||||
This code is experimental and mostly for Justine to save herself from
|
||||
the STL trainwreck. That doesn't mean cosmocc users aren't welcome to
|
||||
use tihs too. You shouldn't expect the design to not change later on.
|
||||
use this too. You shouldn't expect the design to not change later on.
|
||||
|
||||
## Rationale
|
||||
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_EQUAL_H_
|
||||
#define CTL_EQUAL_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt1, class InputIt2>
|
||||
bool
|
||||
equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
|
||||
{
|
||||
for (; first1 != last1; ++first1, ++first2) {
|
||||
if (!(*first1 == *first2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Overload that takes a predicate
|
||||
template<class InputIt1, class InputIt2, class BinaryPredicate>
|
||||
bool
|
||||
equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPredicate pred)
|
||||
{
|
||||
for (; first1 != last1; ++first1, ++first2) {
|
||||
if (!pred(*first1, *first2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Overloads that take two ranges (C++14 and later)
|
||||
template<class InputIt1, class InputIt2>
|
||||
bool
|
||||
equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
|
||||
{
|
||||
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
|
||||
if (!(*first1 == *first2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return first1 == last1 && first2 == last2;
|
||||
}
|
||||
|
||||
template<class InputIt1, class InputIt2, class BinaryPredicate>
|
||||
bool
|
||||
equal(InputIt1 first1,
|
||||
InputIt1 last1,
|
||||
InputIt2 first2,
|
||||
InputIt2 last2,
|
||||
BinaryPredicate pred)
|
||||
{
|
||||
for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
|
||||
if (!pred(*first1, *first2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return first1 == last1 && first2 == last2;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_EQUAL_H_ */
|
||||
@@ -0,0 +1,64 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef _LIBCPP_INITIALIZER_LIST
|
||||
#define _LIBCPP_INITIALIZER_LIST
|
||||
|
||||
namespace std {
|
||||
|
||||
template<class T>
|
||||
class initializer_list
|
||||
{
|
||||
constexpr initializer_list(const T* b, size_t s) noexcept
|
||||
: begin_(b), size_(s)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef const T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef const T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
constexpr initializer_list() noexcept : begin_(nullptr), size_(0)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
constexpr const T* begin() const noexcept
|
||||
{
|
||||
return begin_;
|
||||
}
|
||||
|
||||
constexpr const T* end() const noexcept
|
||||
{
|
||||
return begin_ + size_;
|
||||
}
|
||||
|
||||
private:
|
||||
const T* begin_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline constexpr const T*
|
||||
begin(initializer_list<T> i) noexcept
|
||||
{
|
||||
return i.begin();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline constexpr const T*
|
||||
end(initializer_list<T> i) noexcept
|
||||
{
|
||||
return i.end();
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // _LIBCPP_INITIALIZER_LIST
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_LESS_H_
|
||||
#define CTL_LESS_H_
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T = void>
|
||||
struct less
|
||||
{
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
typedef bool result_type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct less<void>
|
||||
{
|
||||
template<class T, class U>
|
||||
constexpr auto operator()(T&& lhs,
|
||||
U&& rhs) const -> decltype(ctl::forward<T>(lhs) <
|
||||
ctl::forward<U>(rhs))
|
||||
{
|
||||
return ctl::forward<T>(lhs) < ctl::forward<U>(rhs);
|
||||
}
|
||||
|
||||
typedef void is_transparent;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_LESS_H_ */
|
||||
@@ -0,0 +1,352 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_MAP_H_
|
||||
#define CTL_MAP_H_
|
||||
#include "set.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename Key, typename Value, typename Compare = ctl::less<Key>>
|
||||
class map
|
||||
{
|
||||
class EntryCompare
|
||||
{
|
||||
public:
|
||||
explicit EntryCompare(Compare comp = Compare()) : comp_(comp)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const ctl::pair<const Key, Value>& lhs,
|
||||
const ctl::pair<const Key, Value>& rhs) const
|
||||
{
|
||||
return comp_(lhs.first, rhs.first);
|
||||
}
|
||||
|
||||
private:
|
||||
Compare comp_;
|
||||
};
|
||||
|
||||
ctl::set<ctl::pair<const Key, Value>, EntryCompare> data_;
|
||||
|
||||
public:
|
||||
using key_type = Key;
|
||||
using mapped_type = Value;
|
||||
using value_type = ctl::pair<const Key, Value>;
|
||||
using size_type = typename ctl::set<value_type, EntryCompare>::size_type;
|
||||
using difference_type =
|
||||
typename ctl::set<value_type, EntryCompare>::difference_type;
|
||||
using key_compare = Compare;
|
||||
using value_compare = EntryCompare;
|
||||
using iterator = typename ctl::set<value_type, EntryCompare>::iterator;
|
||||
using const_iterator =
|
||||
typename ctl::set<value_type, EntryCompare>::const_iterator;
|
||||
using reverse_iterator =
|
||||
typename ctl::set<value_type, EntryCompare>::reverse_iterator;
|
||||
using const_reverse_iterator =
|
||||
typename ctl::set<value_type, EntryCompare>::const_reverse_iterator;
|
||||
|
||||
map() : data_(EntryCompare())
|
||||
{
|
||||
}
|
||||
|
||||
explicit map(const Compare& comp) : data_(EntryCompare(comp))
|
||||
{
|
||||
}
|
||||
|
||||
map(const map& other) = default;
|
||||
map(map&& other) noexcept = default;
|
||||
map(std::initializer_list<value_type> init, const Compare& comp = Compare())
|
||||
: data_(init, EntryCompare(comp))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename InputIt>
|
||||
map(InputIt first, InputIt last, const Compare& comp = Compare())
|
||||
: data_(first, last, EntryCompare(comp))
|
||||
{
|
||||
}
|
||||
|
||||
map& operator=(const map& other) = default;
|
||||
map& operator=(map&& other) noexcept = default;
|
||||
map& operator=(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
data_ = ilist;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator begin() noexcept
|
||||
{
|
||||
return data_.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return data_.begin();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
return data_.cbegin();
|
||||
}
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
return data_.end();
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return data_.end();
|
||||
}
|
||||
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return data_.cend();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin() noexcept
|
||||
{
|
||||
return data_.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return data_.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return data_.crbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend() noexcept
|
||||
{
|
||||
return data_.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return data_.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return data_.crend();
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return data_.empty();
|
||||
}
|
||||
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
size_type max_size() const noexcept
|
||||
{
|
||||
return data_.max_size();
|
||||
}
|
||||
|
||||
Value& operator[](const Key& key)
|
||||
{
|
||||
return ((data_.insert(make_pair(key, Value()))).first)->second;
|
||||
}
|
||||
|
||||
Value& operator[](Key&& key)
|
||||
{
|
||||
return ((data_.insert(make_pair(ctl::move(key), Value()))).first)
|
||||
->second;
|
||||
}
|
||||
|
||||
Value& at(const Key& key)
|
||||
{
|
||||
auto it = find(key);
|
||||
if (it == end())
|
||||
__builtin_trap();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const Value& at(const Key& key) const
|
||||
{
|
||||
auto it = find(key);
|
||||
if (it == end())
|
||||
__builtin_trap();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ctl::pair<iterator, bool> insert(const value_type& value)
|
||||
{
|
||||
return data_.insert(value);
|
||||
}
|
||||
|
||||
ctl::pair<iterator, bool> insert(value_type&& value)
|
||||
{
|
||||
return data_.insert(ctl::move(value));
|
||||
}
|
||||
|
||||
template<typename P>
|
||||
ctl::pair<iterator, bool> insert(P&& value)
|
||||
{
|
||||
return data_.insert(value_type(ctl::forward<P>(value)));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& value)
|
||||
{
|
||||
return data_.insert(hint, value);
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, value_type&& value)
|
||||
{
|
||||
return data_.insert(hint, ctl::move(value));
|
||||
}
|
||||
|
||||
template<typename P>
|
||||
iterator insert(const_iterator hint, P&& value)
|
||||
{
|
||||
return data_.insert(hint, value_type(ctl::forward<P>(value)));
|
||||
}
|
||||
|
||||
template<typename InputIt>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
data_.insert(first, last);
|
||||
}
|
||||
|
||||
void insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
data_.insert(ilist);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
ctl::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
return data_.emplace(ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return data_.emplace_hint(hint, ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator pos)
|
||||
{
|
||||
return data_.erase(pos);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
return data_.erase(first, last);
|
||||
}
|
||||
|
||||
size_type erase(const Key& key)
|
||||
{
|
||||
return data_.erase(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
void swap(map& other) noexcept
|
||||
{
|
||||
data_.swap(other.data_);
|
||||
}
|
||||
|
||||
void clear() noexcept
|
||||
{
|
||||
data_.clear();
|
||||
}
|
||||
|
||||
iterator find(const Key& key)
|
||||
{
|
||||
return data_.find(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
const_iterator find(const Key& key) const
|
||||
{
|
||||
return data_.find(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
size_type count(const Key& key) const
|
||||
{
|
||||
return data_.count(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
iterator lower_bound(const Key& key)
|
||||
{
|
||||
return data_.lower_bound(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const Key& key) const
|
||||
{
|
||||
return data_.lower_bound(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
iterator upper_bound(const Key& key)
|
||||
{
|
||||
return data_.upper_bound(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const Key& key) const
|
||||
{
|
||||
return data_.upper_bound(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
ctl::pair<iterator, iterator> equal_range(const Key& key)
|
||||
{
|
||||
return data_.equal_range(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
ctl::pair<const_iterator, const_iterator> equal_range(const Key& key) const
|
||||
{
|
||||
return data_.equal_range(make_pair(key, Value()));
|
||||
}
|
||||
|
||||
key_compare key_comp() const
|
||||
{
|
||||
return data_.value_comp().comp;
|
||||
}
|
||||
|
||||
value_compare value_comp() const
|
||||
{
|
||||
return data_.value_comp();
|
||||
}
|
||||
|
||||
friend bool operator==(const map& lhs, const map& rhs)
|
||||
{
|
||||
return lhs.data_ == rhs.data_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const map& lhs, const map& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
friend bool operator<(const map& lhs, const map& rhs)
|
||||
{
|
||||
return lhs.data_ < rhs.data_;
|
||||
}
|
||||
|
||||
friend bool operator<=(const map& lhs, const map& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
friend bool operator>(const map& lhs, const map& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
friend bool operator>=(const map& lhs, const map& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
friend void swap(map& lhs, map& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_MAP_H_
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "new.h"
|
||||
|
||||
#include "libc/mem/mem.h"
|
||||
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
static void*
|
||||
_ctl_alloc(size_t n, size_t a)
|
||||
{
|
||||
void* p;
|
||||
if (!(p = memalign(a, n)))
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
_ctl_alloc1(size_t n)
|
||||
{
|
||||
void* p;
|
||||
if (!(p = malloc(n)))
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
_ctl_ret(size_t, void* p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
_ctl_free(void* p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void
|
||||
_ctl_nop(void*, void*)
|
||||
{
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
||||
#undef __weak_reference
|
||||
#define __weak_reference(P, A) P __attribute__((weak, alias(#A)))
|
||||
|
||||
/* The ISO says that these should be replaceable by user code. It also says
|
||||
that the declarations for the first four (i.e. non placement-) operators
|
||||
new are implicitly available in each translation unit, including the std
|
||||
align_val_t parameter. (?) However, <new> also _defines_ the align_val_t
|
||||
type so you can’t just write your own. Our way through this morass is to
|
||||
supply ours as ctl::align_val_t and not implicitly declare anything, for
|
||||
now. If you have any brain cells left after reading this comment then go
|
||||
look at the eight operator delete weak references to free in the below. */
|
||||
|
||||
__weak_reference(void*
|
||||
operator new(size_t, ctl::align_val_t),
|
||||
_ctl_alloc);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t, ctl::align_val_t),
|
||||
_ctl_alloc);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new(size_t),
|
||||
_ctl_alloc1);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t),
|
||||
_ctl_alloc1);
|
||||
|
||||
// XXX clang-format currently mutilates these for some reason.
|
||||
// clang-format off
|
||||
|
||||
__weak_reference(void* operator new(size_t, void*), _ctl_ret);
|
||||
__weak_reference(void* operator new[](size_t, void*), _ctl_ret);
|
||||
|
||||
__weak_reference(void operator delete(void*) noexcept, _ctl_free);
|
||||
__weak_reference(void operator delete[](void*) noexcept, _ctl_free);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wattribute-alias="
|
||||
__weak_reference(void operator delete(void*, ctl::align_val_t) noexcept,
|
||||
_ctl_free);
|
||||
__weak_reference(void operator delete[](void*, ctl::align_val_t) noexcept,
|
||||
_ctl_free);
|
||||
__weak_reference(void operator delete(void*, size_t) noexcept, _ctl_free);
|
||||
__weak_reference(void operator delete[](void*, size_t) noexcept, _ctl_free);
|
||||
__weak_reference(void operator delete(void*, size_t, ctl::align_val_t) noexcept,
|
||||
_ctl_free);
|
||||
__weak_reference(void operator delete[](void*, size_t, ctl::align_val_t)
|
||||
noexcept, _ctl_free);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
__weak_reference(void operator delete(void*, void*) noexcept, _ctl_nop);
|
||||
__weak_reference(void operator delete[](void*, void*) noexcept, _ctl_nop);
|
||||
@@ -0,0 +1,38 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_NEW_H_
|
||||
#define COSMOPOLITAN_CTL_NEW_H_
|
||||
|
||||
#ifndef TINY
|
||||
__static_yoink("__demangle");
|
||||
#endif
|
||||
|
||||
namespace ctl {
|
||||
|
||||
enum class align_val_t : size_t
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
void* operator new(size_t);
|
||||
void* operator new[](size_t);
|
||||
void* operator new(size_t, ctl::align_val_t);
|
||||
void* operator new[](size_t, ctl::align_val_t);
|
||||
|
||||
// XXX clang-format currently mutilates these for some reason.
|
||||
// clang-format off
|
||||
|
||||
void* operator new(size_t, void*);
|
||||
void* operator new[](size_t, void*);
|
||||
|
||||
void operator delete(void*) noexcept;
|
||||
void operator delete[](void*) noexcept;
|
||||
void operator delete(void*, ctl::align_val_t) noexcept;
|
||||
void operator delete[](void*, ctl::align_val_t) noexcept;
|
||||
void operator delete(void*, size_t) noexcept;
|
||||
void operator delete[](void*, size_t) noexcept;
|
||||
void operator delete(void*, size_t, ctl::align_val_t) noexcept;
|
||||
void operator delete[](void*, size_t, ctl::align_val_t) noexcept;
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_NEW_H_
|
||||
+32
-20
@@ -1,10 +1,9 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#define COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/swap.h>
|
||||
#include "new.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
@@ -14,38 +13,45 @@ class optional
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
~optional() = default;
|
||||
~optional()
|
||||
{
|
||||
if (present_)
|
||||
value_.~T();
|
||||
}
|
||||
|
||||
optional() noexcept : present_(false)
|
||||
{
|
||||
}
|
||||
|
||||
optional(const T& value) : present_(true), value_(value)
|
||||
optional(const T& value) : present_(true)
|
||||
{
|
||||
new (&value_) T(value);
|
||||
}
|
||||
|
||||
optional(T&& value) : present_(true), value_(std::move(value))
|
||||
optional(T&& value) : present_(true)
|
||||
{
|
||||
new (&value_) T(ctl::move(value));
|
||||
}
|
||||
|
||||
optional(const optional& other) : present_(other.present_)
|
||||
{
|
||||
if (present_)
|
||||
if (other.present_)
|
||||
new (&value_) T(other.value_);
|
||||
}
|
||||
|
||||
optional(optional&& other) noexcept : present_(other.present_)
|
||||
{
|
||||
if (present_)
|
||||
value_ = std::move(other.value_);
|
||||
if (other.present_)
|
||||
new (&value_) T(ctl::move(other.value_));
|
||||
}
|
||||
|
||||
optional& operator=(const optional& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
reset();
|
||||
if (other.present_)
|
||||
new (&value_) T(other.value_);
|
||||
present_ = other.present_;
|
||||
if (present_)
|
||||
value_ = other.value_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -53,9 +59,10 @@ class optional
|
||||
optional& operator=(optional&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
reset();
|
||||
if (other.present_)
|
||||
new (&value_) T(ctl::move(other.value_));
|
||||
present_ = other.present_;
|
||||
if (present_)
|
||||
value_ = std::move(other.value_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -78,7 +85,7 @@ class optional
|
||||
{
|
||||
if (!present_)
|
||||
__builtin_trap();
|
||||
return std::move(value_);
|
||||
return ctl::move(value_);
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
@@ -102,26 +109,31 @@ class optional
|
||||
template<typename... Args>
|
||||
void emplace(Args&&... args)
|
||||
{
|
||||
reset();
|
||||
present_ = true;
|
||||
value_ = T(std::forward<Args>(args)...);
|
||||
new (&value_) T(ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void swap(optional& other) noexcept
|
||||
{
|
||||
using ctl::swap;
|
||||
if (present_ && other.present_) {
|
||||
std::swap(value_, other.value_);
|
||||
swap(value_, other.value_);
|
||||
} else if (present_) {
|
||||
other.emplace(std::move(value_));
|
||||
other.emplace(ctl::move(value_));
|
||||
reset();
|
||||
} else if (other.present_) {
|
||||
emplace(std::move(other.value_));
|
||||
emplace(ctl::move(other.value_));
|
||||
other.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union
|
||||
{
|
||||
T value_;
|
||||
};
|
||||
bool present_;
|
||||
T value_;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_PAIR_H_
|
||||
#define CTL_PAIR_H_
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T1, typename T2>
|
||||
struct pair
|
||||
{
|
||||
using first_type = T1;
|
||||
using second_type = T2;
|
||||
|
||||
T1 first;
|
||||
T2 second;
|
||||
|
||||
constexpr pair() : first(), second()
|
||||
{
|
||||
}
|
||||
|
||||
constexpr pair(const T1& x, const T2& y) : first(x), second(y)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr pair(const pair<T1, T2>& p) : first(p.first), second(p.second)
|
||||
{
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
constexpr pair(U1&& x, U2&& y)
|
||||
: first(ctl::forward<U1>(x)), second(ctl::forward<U2>(y))
|
||||
{
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
constexpr pair(const pair<U1, U2>& p) : first(p.first), second(p.second)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr pair(pair<T1, T2>&& p)
|
||||
: first(ctl::move(p.first)), second(ctl::move(p.second))
|
||||
{
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
constexpr pair(pair<U1, U2>&& p)
|
||||
: first(ctl::move(p.first)), second(ctl::move(p.second))
|
||||
{
|
||||
}
|
||||
|
||||
pair& operator=(const pair& other)
|
||||
{
|
||||
first = other.first;
|
||||
second = other.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
pair& operator=(pair&& other) noexcept
|
||||
{
|
||||
first = ctl::move(other.first);
|
||||
second = ctl::move(other.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
pair& operator=(const pair<U1, U2>& other)
|
||||
{
|
||||
first = other.first;
|
||||
second = other.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class U1, class U2>
|
||||
pair& operator=(pair<U1, U2>&& other)
|
||||
{
|
||||
first = ctl::move(other.first);
|
||||
second = ctl::move(other.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(pair& other) noexcept
|
||||
{
|
||||
using ctl::swap;
|
||||
swap(first, other.first);
|
||||
swap(second, other.second);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr pair<T1, T2>
|
||||
make_pair(T1&& t, T2&& u)
|
||||
{
|
||||
return pair<T1, T2>(ctl::forward<T1>(t), ctl::forward<T2>(u));
|
||||
}
|
||||
|
||||
// Comparison operators
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator==(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return lhs.first == rhs.first && lhs.second == rhs.second;
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator!=(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator<(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return lhs.first < rhs.first ||
|
||||
(!(rhs.first < lhs.first) && lhs.second < rhs.second);
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator<=(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator>(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
constexpr bool
|
||||
operator>=(const pair<T1, T2>& lhs, const pair<T1, T2>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
void
|
||||
swap(pair<T1, T2>& lhs, pair<T1, T2>& rhs) noexcept(noexcept(lhs.swap(rhs)))
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_PAIR_H_
|
||||
@@ -0,0 +1,945 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_SET_H_
|
||||
#define CTL_SET_H_
|
||||
#include "initializer_list.h"
|
||||
#include "less.h"
|
||||
#include "pair.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename Key, typename Compare = less<Key>>
|
||||
class set
|
||||
{
|
||||
struct rbtree
|
||||
{
|
||||
rbtree* left;
|
||||
rbtree* right;
|
||||
rbtree* parent;
|
||||
bool is_red;
|
||||
Key value;
|
||||
|
||||
rbtree(const Key& val)
|
||||
: left(nullptr)
|
||||
, right(nullptr)
|
||||
, parent(nullptr)
|
||||
, is_red(true)
|
||||
, value(val)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
using key_type = Key;
|
||||
using value_type = Key;
|
||||
using size_type = size_t;
|
||||
using node_type = rbtree;
|
||||
using key_compare = Compare;
|
||||
using value_compare = Compare;
|
||||
using difference_type = ptrdiff_t;
|
||||
using reference = value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using const_reference = const value_type&;
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
using value_type = Key;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = Key*;
|
||||
using reference = Key&;
|
||||
|
||||
iterator() : node_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
return node_->value;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{
|
||||
return &(node_->value);
|
||||
}
|
||||
|
||||
iterator& operator++()
|
||||
{
|
||||
if (node_ == nullptr)
|
||||
return *this;
|
||||
if (node_->right) {
|
||||
node_ = leftmost(node_->right);
|
||||
} else {
|
||||
node_type* parent = node_->parent;
|
||||
while (parent && node_ == parent->right) {
|
||||
node_ = parent;
|
||||
parent = parent->parent;
|
||||
}
|
||||
node_ = parent;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator& operator--()
|
||||
{
|
||||
if (node_ == nullptr)
|
||||
__builtin_trap();
|
||||
if (node_->left) {
|
||||
node_ = rightmost(node_->left);
|
||||
} else {
|
||||
node_type* parent = node_->parent;
|
||||
for (;;) {
|
||||
if (parent == nullptr)
|
||||
break;
|
||||
if (node_ == parent->left) {
|
||||
node_ = parent;
|
||||
parent = parent->parent;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
node_ = parent;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int)
|
||||
{
|
||||
iterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator operator--(int)
|
||||
{
|
||||
iterator tmp = *this;
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const iterator& other) const
|
||||
{
|
||||
return node_ == other.node_;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class set;
|
||||
node_type* node_;
|
||||
|
||||
explicit iterator(node_type* node) : node_(node)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class reverse_iterator
|
||||
{
|
||||
public:
|
||||
using value_type = Key;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = Key*;
|
||||
using reference = Key&;
|
||||
|
||||
reverse_iterator() : node_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
return node_->value;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{
|
||||
return &(node_->value);
|
||||
}
|
||||
|
||||
reverse_iterator& operator++()
|
||||
{
|
||||
if (node_->left) {
|
||||
node_ = rightmost(node_->left);
|
||||
} else {
|
||||
node_type* parent = node_->parent;
|
||||
while (parent && node_ == parent->left) {
|
||||
node_ = parent;
|
||||
parent = parent->parent;
|
||||
}
|
||||
node_ = parent;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
reverse_iterator operator++(int)
|
||||
{
|
||||
reverse_iterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reverse_iterator& operator--()
|
||||
{
|
||||
if (node_->right) {
|
||||
node_ = leftmost(node_->right);
|
||||
} else {
|
||||
node_type* parent = node_->parent;
|
||||
while (parent && node_ == parent->right) {
|
||||
node_ = parent;
|
||||
parent = parent->parent;
|
||||
}
|
||||
node_ = parent;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
reverse_iterator operator--(int)
|
||||
{
|
||||
reverse_iterator tmp = *this;
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const reverse_iterator& other) const
|
||||
{
|
||||
return node_ == other.node_;
|
||||
}
|
||||
|
||||
bool operator!=(const reverse_iterator& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
iterator base() const
|
||||
{
|
||||
if (node_ == nullptr)
|
||||
return iterator(leftmost(root_));
|
||||
reverse_iterator tmp = *this;
|
||||
++tmp;
|
||||
return iterator(tmp.node_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class set;
|
||||
node_type* node_;
|
||||
|
||||
explicit reverse_iterator(node_type* node) : node_(node)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
using const_iterator = iterator;
|
||||
using const_reverse_iterator = reverse_iterator;
|
||||
|
||||
set() : root_(nullptr), size_(0), comp_(Compare())
|
||||
{
|
||||
}
|
||||
|
||||
explicit set(const Compare& comp) : root_(nullptr), size_(0), comp_(comp)
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
set(InputIt first, InputIt last, const Compare& comp = Compare())
|
||||
: root_(nullptr), size_(0), comp_(comp)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
insert(*first);
|
||||
}
|
||||
|
||||
set(const set& other) : root_(nullptr), size_(0)
|
||||
{
|
||||
if (other.root_) {
|
||||
root_ = copier(other.root_);
|
||||
size_ = other.size_;
|
||||
}
|
||||
}
|
||||
|
||||
set(set&& other) noexcept : root_(other.root_), size_(other.size_)
|
||||
{
|
||||
other.root_ = nullptr;
|
||||
other.size_ = 0;
|
||||
}
|
||||
|
||||
set(std::initializer_list<value_type> init, const Compare& comp = Compare())
|
||||
: root_(nullptr), size_(0), comp_(comp)
|
||||
{
|
||||
for (const auto& value : init)
|
||||
insert(value);
|
||||
}
|
||||
|
||||
~set()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
set& operator=(const set& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
clear();
|
||||
if (other.root_) {
|
||||
root_ = copier(other.root_);
|
||||
size_ = other.size_;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
set& operator=(set&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
clear();
|
||||
root_ = other.root_;
|
||||
size_ = other.size_;
|
||||
other.root_ = nullptr;
|
||||
other.size_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
iterator begin() noexcept
|
||||
{
|
||||
if (root_)
|
||||
return iterator(leftmost(root_));
|
||||
return iterator(nullptr);
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
if (root_)
|
||||
return const_iterator(leftmost(root_));
|
||||
return const_iterator(nullptr);
|
||||
}
|
||||
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{
|
||||
return reverse_iterator(rightmost(root_));
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{
|
||||
return const_reverse_iterator(rightmost(root_));
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const
|
||||
{
|
||||
return const_reverse_iterator(rightmost(root_));
|
||||
}
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
return iterator(nullptr);
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return const_iterator(nullptr);
|
||||
}
|
||||
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
reverse_iterator rend()
|
||||
{
|
||||
return reverse_iterator(nullptr);
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{
|
||||
return const_reverse_iterator(nullptr);
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const
|
||||
{
|
||||
return const_reverse_iterator(nullptr);
|
||||
}
|
||||
|
||||
void clear() noexcept
|
||||
{
|
||||
clearer(root_);
|
||||
root_ = nullptr;
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
pair<iterator, bool> insert(value_type&& value)
|
||||
{
|
||||
return insert_node(new node_type(ctl::move(value)));
|
||||
}
|
||||
|
||||
pair<iterator, bool> insert(const value_type& value)
|
||||
{
|
||||
return insert_node(new node_type(value));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& value)
|
||||
{
|
||||
return insert(value).first;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, value_type&& value)
|
||||
{
|
||||
return insert(ctl::move(value)).first;
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
insert(*first);
|
||||
}
|
||||
|
||||
void insert(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
for (const auto& value : ilist)
|
||||
insert(value);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
value_type value(ctl::forward<Args>(args)...);
|
||||
return insert(ctl::move(value));
|
||||
}
|
||||
|
||||
iterator erase(iterator pos)
|
||||
{
|
||||
node_type* node = pos.node_;
|
||||
iterator res = ++pos;
|
||||
erase_node(node);
|
||||
return res;
|
||||
}
|
||||
|
||||
size_type erase(const key_type& key)
|
||||
{
|
||||
node_type* node = get_element(key);
|
||||
if (node == nullptr)
|
||||
return 0;
|
||||
erase_node(node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
while (first != last)
|
||||
first = erase(first);
|
||||
return iterator(const_cast<node_type*>(last.node_));
|
||||
}
|
||||
|
||||
void swap(set& other) noexcept
|
||||
{
|
||||
ctl::swap(root_, other.root_);
|
||||
ctl::swap(size_, other.size_);
|
||||
}
|
||||
|
||||
pair<iterator, iterator> equal_range(const key_type& key)
|
||||
{
|
||||
return { iterator(get_floor(key)), iterator(get_ceiling(key)) };
|
||||
}
|
||||
|
||||
pair<const_iterator, const_iterator> equal_range(const key_type& key) const
|
||||
{
|
||||
return { const_iterator(get_floor(key)),
|
||||
const_iterator(get_ceiling(key)) };
|
||||
}
|
||||
|
||||
iterator lower_bound(const key_type& key)
|
||||
{
|
||||
return iterator(get_floor(key));
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const key_type& key) const
|
||||
{
|
||||
return const_iterator(get_floor(key));
|
||||
}
|
||||
|
||||
iterator upper_bound(const key_type& key)
|
||||
{
|
||||
return iterator(get_ceiling(key));
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const key_type& key) const
|
||||
{
|
||||
return const_iterator(get_ceiling(key));
|
||||
}
|
||||
|
||||
size_type count(const key_type& key) const
|
||||
{
|
||||
return !!get_element(key);
|
||||
}
|
||||
|
||||
iterator find(const key_type& key)
|
||||
{
|
||||
return iterator(get_element(key));
|
||||
}
|
||||
|
||||
const_iterator find(const key_type& key) const
|
||||
{
|
||||
return const_iterator(get_element(key));
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args)
|
||||
{
|
||||
return emplace(ctl::forward<Args>(args)...).first;
|
||||
}
|
||||
|
||||
void check() const
|
||||
{
|
||||
size_type count = 0;
|
||||
if (root_ != nullptr) {
|
||||
if (root_->is_red)
|
||||
// ILLEGAL TREE: root node must be black
|
||||
__builtin_trap();
|
||||
int black_height = -1;
|
||||
checker(root_, nullptr, 0, black_height);
|
||||
count = tally(root_);
|
||||
}
|
||||
if (count != size_)
|
||||
// ILLEGAL TREE: unexpected number of nodes
|
||||
__builtin_trap();
|
||||
}
|
||||
|
||||
private:
|
||||
static node_type* leftmost(node_type* node) noexcept
|
||||
{
|
||||
while (node && node->left)
|
||||
node = node->left;
|
||||
return node;
|
||||
}
|
||||
|
||||
static node_type* rightmost(node_type* node) noexcept
|
||||
{
|
||||
while (node && node->right)
|
||||
node = node->right;
|
||||
return node;
|
||||
}
|
||||
|
||||
static void clearer(node_type* node) noexcept
|
||||
{
|
||||
node_type* right;
|
||||
for (; node; node = right) {
|
||||
right = node->right;
|
||||
clearer(node->left);
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
static node_type* copier(const node_type* node)
|
||||
{
|
||||
if (node == nullptr)
|
||||
return nullptr;
|
||||
node_type* new_node = new node_type(node->value);
|
||||
new_node->left = copier(node->left);
|
||||
new_node->right = copier(node->right);
|
||||
if (new_node->left)
|
||||
new_node->left->parent = new_node;
|
||||
if (new_node->right)
|
||||
new_node->right->parent = new_node;
|
||||
return new_node;
|
||||
}
|
||||
|
||||
static size_type tally(const node_type* node)
|
||||
{
|
||||
if (node == nullptr)
|
||||
return 0;
|
||||
return 1 + tally(node->left) + tally(node->right);
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
node_type* get_element(const K& key) const
|
||||
{
|
||||
node_type* current = root_;
|
||||
while (current != nullptr) {
|
||||
if (comp_(key, current->value)) {
|
||||
current = current->left;
|
||||
} else if (comp_(current->value, key)) {
|
||||
current = current->right;
|
||||
} else {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
node_type* get_floor(const K& key) const
|
||||
{
|
||||
node_type* result = nullptr;
|
||||
node_type* current = root_;
|
||||
while (current != nullptr) {
|
||||
if (!comp_(current->value, key)) {
|
||||
result = current;
|
||||
current = current->left;
|
||||
} else {
|
||||
current = current->right;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename K>
|
||||
node_type* get_ceiling(const K& key) const
|
||||
{
|
||||
node_type* result = nullptr;
|
||||
node_type* current = root_;
|
||||
while (current != nullptr) {
|
||||
if (comp_(key, current->value)) {
|
||||
result = current;
|
||||
current = current->left;
|
||||
} else {
|
||||
current = current->right;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pair<iterator, bool> insert_node(node_type* node)
|
||||
{
|
||||
if (root_ == nullptr) {
|
||||
root_ = node;
|
||||
root_->is_red = false;
|
||||
size_++;
|
||||
return { iterator(root_), true };
|
||||
}
|
||||
node_type* current = root_;
|
||||
node_type* parent = nullptr;
|
||||
while (current != nullptr) {
|
||||
parent = current;
|
||||
if (comp_(node->value, current->value)) {
|
||||
current = current->left;
|
||||
} else if (comp_(current->value, node->value)) {
|
||||
current = current->right;
|
||||
} else {
|
||||
delete node; // already exists
|
||||
return { iterator(current), false };
|
||||
}
|
||||
}
|
||||
if (comp_(node->value, parent->value)) {
|
||||
parent->left = node;
|
||||
} else {
|
||||
parent->right = node;
|
||||
}
|
||||
node->parent = parent;
|
||||
size_++;
|
||||
rebalance_after_insert(node);
|
||||
return { iterator(node), true };
|
||||
}
|
||||
|
||||
void erase_node(node_type* node)
|
||||
{
|
||||
node_type* y = node;
|
||||
node_type* x = nullptr;
|
||||
node_type* x_parent = nullptr;
|
||||
bool y_original_color = y->is_red;
|
||||
if (node->left == nullptr) {
|
||||
x = node->right;
|
||||
transplant(node, node->right);
|
||||
x_parent = node->parent;
|
||||
} else if (node->right == nullptr) {
|
||||
x = node->left;
|
||||
transplant(node, node->left);
|
||||
x_parent = node->parent;
|
||||
} else {
|
||||
y = leftmost(node->right);
|
||||
y_original_color = y->is_red;
|
||||
x = y->right;
|
||||
if (y->parent == node) {
|
||||
if (x)
|
||||
x->parent = y;
|
||||
x_parent = y;
|
||||
} else {
|
||||
transplant(y, y->right);
|
||||
y->right = node->right;
|
||||
y->right->parent = y;
|
||||
x_parent = y->parent;
|
||||
}
|
||||
transplant(node, y);
|
||||
y->left = node->left;
|
||||
y->left->parent = y;
|
||||
y->is_red = node->is_red;
|
||||
}
|
||||
if (!y_original_color)
|
||||
rebalance_after_erase(x, x_parent);
|
||||
delete node;
|
||||
--size_;
|
||||
}
|
||||
|
||||
void left_rotate(node_type* x)
|
||||
{
|
||||
node_type* y = x->right;
|
||||
x->right = y->left;
|
||||
if (y->left != nullptr)
|
||||
y->left->parent = x;
|
||||
y->parent = x->parent;
|
||||
if (x->parent == nullptr) {
|
||||
root_ = y;
|
||||
} else if (x == x->parent->left) {
|
||||
x->parent->left = y;
|
||||
} else {
|
||||
x->parent->right = y;
|
||||
}
|
||||
y->left = x;
|
||||
x->parent = y;
|
||||
}
|
||||
|
||||
void right_rotate(node_type* y)
|
||||
{
|
||||
node_type* x = y->left;
|
||||
y->left = x->right;
|
||||
if (x->right != nullptr)
|
||||
x->right->parent = y;
|
||||
x->parent = y->parent;
|
||||
if (y->parent == nullptr) {
|
||||
root_ = x;
|
||||
} else if (y == y->parent->right) {
|
||||
y->parent->right = x;
|
||||
} else {
|
||||
y->parent->left = x;
|
||||
}
|
||||
x->right = y;
|
||||
y->parent = x;
|
||||
}
|
||||
|
||||
void transplant(node_type* u, node_type* v)
|
||||
{
|
||||
if (u->parent == nullptr) {
|
||||
root_ = v;
|
||||
} else if (u == u->parent->left) {
|
||||
u->parent->left = v;
|
||||
} else {
|
||||
u->parent->right = v;
|
||||
}
|
||||
if (v != nullptr)
|
||||
v->parent = u->parent;
|
||||
}
|
||||
|
||||
void checker(const node_type* node,
|
||||
const node_type* parent,
|
||||
int black_count,
|
||||
int& black_height) const
|
||||
{
|
||||
if (node == nullptr) {
|
||||
// Leaf nodes are considered black
|
||||
if (black_height == -1) {
|
||||
black_height = black_count;
|
||||
} else if (black_count != black_height) {
|
||||
// ILLEGAL TREE: Black height mismatch
|
||||
__builtin_trap();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (node->parent != parent)
|
||||
// ILLEGAL TREE: Parent link is incorrect
|
||||
__builtin_trap();
|
||||
if (parent) {
|
||||
if (parent->left == node && !comp_(node->value, parent->value))
|
||||
// ILLEGAL TREE: Binary search property violated on left child
|
||||
__builtin_trap();
|
||||
if (parent->right == node && !comp_(parent->value, node->value))
|
||||
// ILLEGAL TREE: Binary search property violated on right child
|
||||
__builtin_trap();
|
||||
}
|
||||
if (!node->is_red) {
|
||||
black_count++;
|
||||
} else if (parent != nullptr && parent->is_red) {
|
||||
// ILLEGAL TREE: Red node has red child
|
||||
__builtin_trap();
|
||||
}
|
||||
checker(node->left, node, black_count, black_height);
|
||||
checker(node->right, node, black_count, black_height);
|
||||
}
|
||||
|
||||
void rebalance_after_insert(node_type* node)
|
||||
{
|
||||
node->is_red = true;
|
||||
while (node != root_ && node->parent->is_red) {
|
||||
if (node->parent == node->parent->parent->left) {
|
||||
node_type* uncle = node->parent->parent->right;
|
||||
if (uncle && uncle->is_red) {
|
||||
node->parent->is_red = false;
|
||||
uncle->is_red = false;
|
||||
node->parent->parent->is_red = true;
|
||||
node = node->parent->parent;
|
||||
} else {
|
||||
if (node == node->parent->right) {
|
||||
node = node->parent;
|
||||
left_rotate(node);
|
||||
}
|
||||
node->parent->is_red = false;
|
||||
node->parent->parent->is_red = true;
|
||||
right_rotate(node->parent->parent);
|
||||
}
|
||||
} else {
|
||||
node_type* uncle = node->parent->parent->left;
|
||||
if (uncle && uncle->is_red) {
|
||||
node->parent->is_red = false;
|
||||
uncle->is_red = false;
|
||||
node->parent->parent->is_red = true;
|
||||
node = node->parent->parent;
|
||||
} else {
|
||||
if (node == node->parent->left) {
|
||||
node = node->parent;
|
||||
right_rotate(node);
|
||||
}
|
||||
node->parent->is_red = false;
|
||||
node->parent->parent->is_red = true;
|
||||
left_rotate(node->parent->parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
root_->is_red = false;
|
||||
}
|
||||
|
||||
void rebalance_after_erase(node_type* node, node_type* parent)
|
||||
{
|
||||
while (node != root_ && (node == nullptr || !node->is_red)) {
|
||||
if (node == parent->left) {
|
||||
node_type* sibling = parent->right;
|
||||
if (sibling->is_red) {
|
||||
sibling->is_red = false;
|
||||
parent->is_red = true;
|
||||
left_rotate(parent);
|
||||
sibling = parent->right;
|
||||
}
|
||||
if ((sibling->left == nullptr || !sibling->left->is_red) &&
|
||||
(sibling->right == nullptr || !sibling->right->is_red)) {
|
||||
sibling->is_red = true;
|
||||
node = parent;
|
||||
parent = node->parent;
|
||||
} else {
|
||||
if (sibling->right == nullptr || !sibling->right->is_red) {
|
||||
sibling->left->is_red = false;
|
||||
sibling->is_red = true;
|
||||
right_rotate(sibling);
|
||||
sibling = parent->right;
|
||||
}
|
||||
sibling->is_red = parent->is_red;
|
||||
parent->is_red = false;
|
||||
sibling->right->is_red = false;
|
||||
left_rotate(parent);
|
||||
node = root_;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
node_type* sibling = parent->left;
|
||||
if (sibling->is_red) {
|
||||
sibling->is_red = false;
|
||||
parent->is_red = true;
|
||||
right_rotate(parent);
|
||||
sibling = parent->left;
|
||||
}
|
||||
if ((sibling->right == nullptr || !sibling->right->is_red) &&
|
||||
(sibling->left == nullptr || !sibling->left->is_red)) {
|
||||
sibling->is_red = true;
|
||||
node = parent;
|
||||
parent = node->parent;
|
||||
} else {
|
||||
if (sibling->left == nullptr || !sibling->left->is_red) {
|
||||
sibling->right->is_red = false;
|
||||
sibling->is_red = true;
|
||||
left_rotate(sibling);
|
||||
sibling = parent->left;
|
||||
}
|
||||
sibling->is_red = parent->is_red;
|
||||
parent->is_red = false;
|
||||
sibling->left->is_red = false;
|
||||
right_rotate(parent);
|
||||
node = root_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node != nullptr)
|
||||
node->is_red = false;
|
||||
}
|
||||
|
||||
node_type* root_;
|
||||
size_type size_;
|
||||
Compare comp_;
|
||||
};
|
||||
|
||||
template<class Key, typename Compare = less<Key>>
|
||||
bool
|
||||
operator==(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
|
||||
{
|
||||
if (lhs.size() != rhs.size())
|
||||
return false;
|
||||
auto i = lhs.cbegin();
|
||||
auto j = rhs.cbegin();
|
||||
for (; i != lhs.end(); ++i, ++j) {
|
||||
if (!(*i == *j))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Key, typename Compare = less<Key>>
|
||||
bool
|
||||
operator<(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
|
||||
{
|
||||
auto i = lhs.cbegin();
|
||||
auto j = rhs.cbegin();
|
||||
for (; i != lhs.end() && j != rhs.end(); ++i, ++j) {
|
||||
if (Compare()(*i, *j))
|
||||
return true;
|
||||
if (Compare()(*j, *i))
|
||||
return false;
|
||||
}
|
||||
return i == lhs.end() && j != rhs.end();
|
||||
}
|
||||
|
||||
template<class Key, typename Compare = less<Key>>
|
||||
bool
|
||||
operator!=(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<class Key, typename Compare = less<Key>>
|
||||
bool
|
||||
operator<=(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template<class Key, typename Compare = less<Key>>
|
||||
bool
|
||||
operator>(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<class Key, typename Compare = less<Key>>
|
||||
bool
|
||||
operator>=(const set<Key, Compare>& lhs, const set<Key, Compare>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<class Key, typename Compare = less<Key>>
|
||||
void
|
||||
swap(set<Key, Compare>& lhs, set<Key, Compare>& rhs) noexcept;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_SET_H_
|
||||
+9
-4
@@ -1,5 +1,5 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
@@ -34,10 +34,15 @@ strcat(const string_view lhs, const string_view rhs) noexcept
|
||||
__builtin_trap();
|
||||
res.reserve(need);
|
||||
if (lhs.n)
|
||||
memcpy(res.p, lhs.p, lhs.n);
|
||||
memcpy(res.data(), lhs.p, lhs.n);
|
||||
if (rhs.n)
|
||||
memcpy(res.p + lhs.n, rhs.p, rhs.n);
|
||||
res.p[res.n = lhs.n + rhs.n] = 0;
|
||||
memcpy(res.data() + lhs.n, rhs.p, rhs.n);
|
||||
if (res.isbig()) {
|
||||
res.big()->n = lhs.n + rhs.n;
|
||||
} else {
|
||||
res.small()->rem = __::sso_max - lhs.n - rhs.n;
|
||||
}
|
||||
res.data()[res.size()] = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
|
||||
+185
-121
@@ -1,5 +1,5 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
@@ -23,180 +23,227 @@
|
||||
|
||||
namespace ctl {
|
||||
|
||||
string::~string() noexcept
|
||||
void
|
||||
string::destroy_big() noexcept
|
||||
{
|
||||
if (n) {
|
||||
if (n >= c)
|
||||
auto* b = big();
|
||||
if (b->n) {
|
||||
if (b->n >= b->c)
|
||||
__builtin_trap();
|
||||
if (p[n])
|
||||
if (b->p[b->n])
|
||||
__builtin_trap();
|
||||
}
|
||||
if (c && !p)
|
||||
if (b->c && !b->p)
|
||||
__builtin_trap();
|
||||
free(p);
|
||||
free(b->p);
|
||||
}
|
||||
|
||||
string::string(const char* s) noexcept
|
||||
void
|
||||
string::init_big(const string& s) noexcept
|
||||
{
|
||||
append(s, strlen(s));
|
||||
char* p2;
|
||||
#ifndef NDEBUG
|
||||
if (!s.isbig())
|
||||
__builtin_trap();
|
||||
#endif
|
||||
if (s.size() >= s.capacity() >> 1) {
|
||||
if (!(p2 = (char*)malloc(s.capacity())))
|
||||
__builtin_trap();
|
||||
set_big_string(p2, s.size(), s.capacity());
|
||||
} else {
|
||||
init_big(string_view(s));
|
||||
}
|
||||
}
|
||||
|
||||
string::string(const string& s) noexcept
|
||||
void
|
||||
string::init_big(const string_view s) noexcept
|
||||
{
|
||||
append(s.p, s.n);
|
||||
size_t need;
|
||||
char* p2;
|
||||
if (ckd_add(&need, s.n, 1 /* nul */ + 15))
|
||||
__builtin_trap();
|
||||
need &= -16;
|
||||
if (!(p2 = (char*)malloc(need)))
|
||||
__builtin_trap();
|
||||
memcpy(p2, s.p, s.n);
|
||||
p2[s.n] = 0;
|
||||
set_big_string(p2, s.n, need);
|
||||
}
|
||||
|
||||
string::string(const string_view s) noexcept
|
||||
void
|
||||
string::init_big(const size_t n, const char ch) noexcept
|
||||
{
|
||||
append(s.p, s.n);
|
||||
}
|
||||
|
||||
string::string(size_t size, char ch) noexcept
|
||||
{
|
||||
resize(size, ch);
|
||||
}
|
||||
|
||||
string::string(const char* s, size_t size) noexcept
|
||||
{
|
||||
append(s, size);
|
||||
size_t need;
|
||||
char* p2;
|
||||
if (ckd_add(&need, n, 1 /* nul */ + 15))
|
||||
__builtin_trap();
|
||||
need &= -16;
|
||||
if (!(p2 = (char*)malloc(need)))
|
||||
__builtin_trap();
|
||||
memset(p2, ch, n);
|
||||
p2[n] = 0;
|
||||
set_big_string(p2, n, need);
|
||||
}
|
||||
|
||||
const char*
|
||||
string::c_str() const noexcept
|
||||
{
|
||||
if (!n)
|
||||
if (!size())
|
||||
return "";
|
||||
if (n >= c)
|
||||
if (size() >= capacity())
|
||||
__builtin_trap();
|
||||
if (p[n])
|
||||
if (data()[size()])
|
||||
__builtin_trap();
|
||||
return p;
|
||||
return data();
|
||||
}
|
||||
|
||||
void
|
||||
string::reserve(size_t c2) noexcept
|
||||
{
|
||||
char* p2;
|
||||
if (c2 < n)
|
||||
c2 = n;
|
||||
size_t n = size();
|
||||
if (c2 < n + 1)
|
||||
c2 = n + 1;
|
||||
if (c2 <= __::string_size)
|
||||
return;
|
||||
if (ckd_add(&c2, c2, 15))
|
||||
__builtin_trap();
|
||||
c2 &= -16;
|
||||
if (!(p2 = (char*)realloc(p, c2)))
|
||||
__builtin_trap();
|
||||
if (!isbig()) {
|
||||
if (!(p2 = (char*)malloc(c2)))
|
||||
__builtin_trap();
|
||||
memcpy(p2, data(), __::string_size);
|
||||
} else {
|
||||
if (!(p2 = (char*)realloc(big()->p, c2)))
|
||||
__builtin_trap();
|
||||
}
|
||||
std::atomic_signal_fence(std::memory_order_seq_cst);
|
||||
c = c2;
|
||||
p = p2;
|
||||
set_big_string(p2, n, c2);
|
||||
}
|
||||
|
||||
void
|
||||
string::resize(size_t n2, char ch) noexcept
|
||||
string::resize(const size_t n2, const char ch) noexcept
|
||||
{
|
||||
size_t c2;
|
||||
if (ckd_add(&c2, n2, 1))
|
||||
__builtin_trap();
|
||||
reserve(c2);
|
||||
if (n2 > n)
|
||||
memset(p + n, ch, n2 - n);
|
||||
p[n = n2] = 0;
|
||||
if (n2 > size())
|
||||
memset(data() + size(), ch, n2 - size());
|
||||
if (isbig()) {
|
||||
big()->p[big()->n = n2] = 0;
|
||||
} else {
|
||||
set_small_size(n2);
|
||||
data()[size()] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
string::append(char ch) noexcept
|
||||
string::append(const char ch) noexcept
|
||||
{
|
||||
if (n + 2 > c) {
|
||||
size_t c2 = c + 2;
|
||||
c2 += c2 >> 1;
|
||||
size_t n2;
|
||||
if (ckd_add(&n2, size(), 2))
|
||||
__builtin_trap();
|
||||
if (n2 > capacity()) {
|
||||
size_t c2 = capacity();
|
||||
if (ckd_add(&c2, c2, c2 >> 1))
|
||||
__builtin_trap();
|
||||
reserve(c2);
|
||||
}
|
||||
p[n++] = ch;
|
||||
p[n] = 0;
|
||||
data()[size()] = ch;
|
||||
if (isbig()) {
|
||||
++big()->n;
|
||||
} else {
|
||||
--small()->rem;
|
||||
}
|
||||
data()[size()] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
string::grow(size_t size) noexcept
|
||||
string::grow(const size_t size) noexcept
|
||||
{
|
||||
size_t need;
|
||||
if (ckd_add(&need, n, size))
|
||||
if (ckd_add(&need, this->size(), size))
|
||||
__builtin_trap();
|
||||
if (ckd_add(&need, need, 1))
|
||||
__builtin_trap();
|
||||
if (need <= c)
|
||||
if (need <= capacity())
|
||||
return;
|
||||
size_t c2 = c;
|
||||
if (!c2) {
|
||||
c2 = need;
|
||||
} else {
|
||||
while (c2 < need)
|
||||
if (ckd_add(&c2, c2, c2 >> 1))
|
||||
__builtin_trap();
|
||||
}
|
||||
size_t c2 = capacity();
|
||||
if (!c2)
|
||||
__builtin_trap();
|
||||
while (c2 < need)
|
||||
if (ckd_add(&c2, c2, c2 >> 1))
|
||||
__builtin_trap();
|
||||
reserve(c2);
|
||||
}
|
||||
|
||||
void
|
||||
string::append(char ch, size_t size) noexcept
|
||||
string::append(const char ch, const size_t size) noexcept
|
||||
{
|
||||
grow(size);
|
||||
if (size)
|
||||
memset(p + n, ch, size);
|
||||
p[n += size] = 0;
|
||||
memset(data() + this->size(), ch, size);
|
||||
if (isbig()) {
|
||||
big()->n += size;
|
||||
} else {
|
||||
small()->rem -= size;
|
||||
}
|
||||
data()[this->size()] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
string::append(const void* data, size_t size) noexcept
|
||||
string::append(const void* data, const size_t size) noexcept
|
||||
{
|
||||
grow(size);
|
||||
if (size)
|
||||
memcpy(p + n, data, size);
|
||||
p[n += size] = 0;
|
||||
memcpy(this->data() + this->size(), data, size);
|
||||
if (isbig()) {
|
||||
big()->n += size;
|
||||
} else {
|
||||
small()->rem -= size;
|
||||
}
|
||||
this->data()[this->size()] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
string::pop_back() noexcept
|
||||
{
|
||||
if (!n)
|
||||
if (!size())
|
||||
__builtin_trap();
|
||||
p[--n] = 0;
|
||||
if (isbig()) {
|
||||
--big()->n;
|
||||
} else {
|
||||
++small()->rem;
|
||||
}
|
||||
data()[size()] = 0;
|
||||
}
|
||||
|
||||
string&
|
||||
string::operator=(string&& s) noexcept
|
||||
string::operator=(string s) noexcept
|
||||
{
|
||||
if (p != s.p) {
|
||||
if (p) {
|
||||
clear();
|
||||
append(s.p, s.n);
|
||||
} else {
|
||||
p = s.p;
|
||||
n = s.n;
|
||||
c = s.c;
|
||||
s.p = nullptr;
|
||||
s.n = 0;
|
||||
s.c = 0;
|
||||
}
|
||||
}
|
||||
swap(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
string::operator==(const string_view s) const noexcept
|
||||
{
|
||||
if (n != s.n)
|
||||
if (size() != s.n)
|
||||
return false;
|
||||
if (!n)
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !memcmp(p, s.p, n);
|
||||
return !memcmp(data(), s.p, s.n);
|
||||
}
|
||||
|
||||
bool
|
||||
string::operator!=(const string_view s) const noexcept
|
||||
{
|
||||
if (n != s.n)
|
||||
if (size() != s.n)
|
||||
return true;
|
||||
if (!n)
|
||||
if (!s.n)
|
||||
return false;
|
||||
return !!memcmp(p, s.p, n);
|
||||
return !!memcmp(data(), s.p, s.n);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -204,76 +251,78 @@ string::contains(const string_view s) const noexcept
|
||||
{
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !!memmem(p, n, s.p, s.n);
|
||||
return !!memmem(data(), size(), s.p, s.n);
|
||||
}
|
||||
|
||||
bool
|
||||
string::ends_with(const string_view s) const noexcept
|
||||
{
|
||||
if (n < s.n)
|
||||
if (size() < s.n)
|
||||
return false;
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !memcmp(p + n - s.n, s.p, s.n);
|
||||
return !memcmp(data() + size() - s.n, s.p, s.n);
|
||||
}
|
||||
|
||||
bool
|
||||
string::starts_with(const string_view s) const noexcept
|
||||
{
|
||||
if (n < s.n)
|
||||
if (size() < s.n)
|
||||
return false;
|
||||
if (!s.n)
|
||||
return true;
|
||||
return !memcmp(p, s.p, s.n);
|
||||
return !memcmp(data(), s.p, s.n);
|
||||
}
|
||||
|
||||
size_t
|
||||
string::find(char ch, size_t pos) const noexcept
|
||||
string::find(const char ch, const size_t pos) const noexcept
|
||||
{
|
||||
char* q;
|
||||
if ((q = (char*)memchr(p, ch, n)))
|
||||
return q - p;
|
||||
if ((q = (char*)memchr(data(), ch, size())))
|
||||
return q - data();
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t
|
||||
string::find(const string_view s, size_t pos) const noexcept
|
||||
string::find(const string_view s, const size_t pos) const noexcept
|
||||
{
|
||||
char* q;
|
||||
if (pos > n)
|
||||
if (pos > size())
|
||||
__builtin_trap();
|
||||
if ((q = (char*)memmem(p + pos, n - pos, s.p, s.n)))
|
||||
return q - p;
|
||||
if ((q = (char*)memmem(data() + pos, size() - pos, s.p, s.n)))
|
||||
return q - data();
|
||||
return npos;
|
||||
}
|
||||
|
||||
string
|
||||
string::substr(size_t pos, size_t count) const noexcept
|
||||
string::substr(const size_t pos, size_t count) const noexcept
|
||||
{
|
||||
size_t last;
|
||||
if (pos > n)
|
||||
if (pos > size())
|
||||
__builtin_trap();
|
||||
if (count > n - pos)
|
||||
count = n - pos;
|
||||
if (count > size() - pos)
|
||||
count = size() - pos;
|
||||
if (ckd_add(&last, pos, count))
|
||||
last = n;
|
||||
if (last > n)
|
||||
last = size();
|
||||
if (last > size())
|
||||
__builtin_trap();
|
||||
return string(p + pos, count);
|
||||
return string(data() + pos, count);
|
||||
}
|
||||
|
||||
string&
|
||||
string::replace(size_t pos, size_t count, const string_view& s) noexcept
|
||||
string::replace(const size_t pos,
|
||||
const size_t count,
|
||||
const string_view s) noexcept
|
||||
{
|
||||
size_t last;
|
||||
if (ckd_add(&last, pos, count))
|
||||
__builtin_trap();
|
||||
if (last > n)
|
||||
if (last > size())
|
||||
__builtin_trap();
|
||||
size_t need;
|
||||
if (ckd_add(&need, pos, s.n))
|
||||
__builtin_trap();
|
||||
size_t extra = n - last;
|
||||
size_t extra = size() - last;
|
||||
if (ckd_add(&need, need, extra))
|
||||
__builtin_trap();
|
||||
size_t c2;
|
||||
@@ -281,42 +330,57 @@ string::replace(size_t pos, size_t count, const string_view& s) noexcept
|
||||
__builtin_trap();
|
||||
reserve(c2);
|
||||
if (extra)
|
||||
memmove(p + pos + s.n, p + last, extra);
|
||||
memcpy(p + pos, s.p, s.n);
|
||||
p[n = need] = 0;
|
||||
memmove(data() + pos + s.n, data() + last, extra);
|
||||
memcpy(data() + pos, s.p, s.n);
|
||||
if (isbig()) {
|
||||
big()->p[big()->n = need] = 0;
|
||||
} else {
|
||||
set_small_size(need);
|
||||
data()[size()] = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::insert(size_t i, const string_view s) noexcept
|
||||
string::insert(const size_t i, const string_view s) noexcept
|
||||
{
|
||||
if (i > n)
|
||||
if (i > size())
|
||||
__builtin_trap();
|
||||
size_t extra = n - i;
|
||||
size_t extra = size() - i;
|
||||
size_t need;
|
||||
if (ckd_add(&need, n, s.n))
|
||||
if (ckd_add(&need, size(), s.n))
|
||||
__builtin_trap();
|
||||
if (ckd_add(&need, need, 1))
|
||||
__builtin_trap();
|
||||
reserve(need);
|
||||
if (extra)
|
||||
memmove(p + i + s.n, p + i, extra);
|
||||
memcpy(p + i, s.p, s.n);
|
||||
p[n += s.n] = 0;
|
||||
memmove(data() + i + s.n, data() + i, extra);
|
||||
memcpy(data() + i, s.p, s.n);
|
||||
if (isbig()) {
|
||||
big()->n += s.n;
|
||||
} else {
|
||||
small()->rem -= s.n;
|
||||
}
|
||||
data()[size()] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::erase(size_t pos, size_t count) noexcept
|
||||
string::erase(const size_t pos, size_t count) noexcept
|
||||
{
|
||||
if (pos > n)
|
||||
if (pos > size())
|
||||
__builtin_trap();
|
||||
if (count > n - pos)
|
||||
count = n - pos;
|
||||
size_t extra = n - (pos + count);
|
||||
if (count > size() - pos)
|
||||
count = size() - pos;
|
||||
size_t extra = size() - (pos + count);
|
||||
if (extra)
|
||||
memmove(p + pos, p + pos + count, extra);
|
||||
p[n = pos + extra] = 0;
|
||||
memmove(data() + pos, data() + pos + count, extra);
|
||||
if (isbig()) {
|
||||
big()->n = pos + extra;
|
||||
} else {
|
||||
set_small_size(pos + extra);
|
||||
}
|
||||
data()[size()] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
+223
-59
@@ -1,34 +1,109 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_STRING_H_
|
||||
#define COSMOPOLITAN_CTL_STRING_H_
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_STRING_H_
|
||||
#define CTL_STRING_H_
|
||||
#include "string_view.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
struct string;
|
||||
class string;
|
||||
|
||||
string
|
||||
strcat(const string_view, const string_view) noexcept __wur;
|
||||
string strcat(string_view, string_view) noexcept __wur;
|
||||
|
||||
struct string
|
||||
namespace __ {
|
||||
|
||||
constexpr size_t string_size = 3 * sizeof(size_t);
|
||||
constexpr size_t sso_max = string_size - 1;
|
||||
constexpr size_t big_mask = ~(1ull << (8ull * sizeof(size_t) - 1ull));
|
||||
|
||||
struct small_string
|
||||
{
|
||||
char* p = nullptr;
|
||||
size_t n = 0;
|
||||
size_t c = 0;
|
||||
char buf[sso_max];
|
||||
// interpretation is: size == sso_max - rem
|
||||
unsigned char rem;
|
||||
#if 0
|
||||
size_t rem : 7;
|
||||
size_t big : 1 /* = 0 */;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct big_string
|
||||
{
|
||||
char* p;
|
||||
size_t n;
|
||||
// interpretation is: capacity == c & big_mask
|
||||
size_t c;
|
||||
#if 0
|
||||
size_t c : sizeof(size_t) * 8 - 1;
|
||||
size_t big : 1 /* = 1 */;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace __
|
||||
|
||||
class string
|
||||
{
|
||||
public:
|
||||
using iterator = char*;
|
||||
using const_iterator = const char*;
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
~string() noexcept;
|
||||
string() = default;
|
||||
string(const string_view) noexcept;
|
||||
string(const char*) noexcept;
|
||||
string(const string&) noexcept;
|
||||
string(const char*, size_t) noexcept;
|
||||
explicit string(size_t, char = 0) noexcept;
|
||||
string& operator=(string&&) noexcept;
|
||||
string() noexcept
|
||||
{
|
||||
__builtin_memset(blob, 0, sizeof(size_t) * 2);
|
||||
// equivalent to set_small_size(0) but also zeroes memory
|
||||
*(((size_t*)blob) + 2) = __::sso_max << (sizeof(size_t) - 1) * 8;
|
||||
}
|
||||
|
||||
string(const string_view s) noexcept
|
||||
{
|
||||
if (s.n <= __::sso_max) {
|
||||
__builtin_memcpy(blob, s.p, s.n);
|
||||
__builtin_memset(blob + s.n, 0, __::sso_max - s.n);
|
||||
set_small_size(s.n);
|
||||
} else {
|
||||
init_big(s);
|
||||
}
|
||||
}
|
||||
|
||||
explicit string(const size_t n, const char ch = 0) noexcept
|
||||
{
|
||||
if (n <= __::sso_max) {
|
||||
__builtin_memset(blob, ch, n);
|
||||
__builtin_memset(blob + n, 0, __::sso_max - n);
|
||||
set_small_size(n);
|
||||
} else {
|
||||
init_big(n, ch);
|
||||
}
|
||||
}
|
||||
|
||||
string(const char* const p) noexcept
|
||||
: string(string_view(p, __builtin_strlen(p)))
|
||||
{
|
||||
}
|
||||
|
||||
string(const string& r) noexcept
|
||||
{
|
||||
if (r.size() <= __::sso_max) {
|
||||
__builtin_memcpy(blob, r.data(), __::string_size);
|
||||
set_small_size(r.size());
|
||||
} else {
|
||||
init_big(r);
|
||||
}
|
||||
}
|
||||
|
||||
string(const char* const p, const size_t n) noexcept
|
||||
: string(string_view(p, n))
|
||||
{
|
||||
}
|
||||
|
||||
~string() /* noexcept */
|
||||
{
|
||||
if (isbig())
|
||||
destroy_big();
|
||||
}
|
||||
|
||||
string& operator=(string) noexcept;
|
||||
const char* c_str() const noexcept;
|
||||
|
||||
void pop_back() noexcept;
|
||||
@@ -39,118 +114,139 @@ struct string
|
||||
void append(char, size_t) noexcept;
|
||||
void append(unsigned long) noexcept;
|
||||
void append(const void*, size_t) noexcept;
|
||||
string& insert(size_t, const string_view) noexcept;
|
||||
string& insert(size_t, string_view) noexcept;
|
||||
string& erase(size_t = 0, size_t = npos) noexcept;
|
||||
string substr(size_t = 0, size_t = npos) const noexcept;
|
||||
string& replace(size_t, size_t, const string_view&) noexcept;
|
||||
bool operator==(const string_view) const noexcept;
|
||||
bool operator!=(const string_view) const noexcept;
|
||||
bool contains(const string_view) const noexcept;
|
||||
bool ends_with(const string_view) const noexcept;
|
||||
bool starts_with(const string_view) const noexcept;
|
||||
string& replace(size_t, size_t, string_view) noexcept;
|
||||
bool operator==(string_view) const noexcept;
|
||||
bool operator!=(string_view) const noexcept;
|
||||
bool contains(string_view) const noexcept;
|
||||
bool ends_with(string_view) const noexcept;
|
||||
bool starts_with(string_view) const noexcept;
|
||||
size_t find(char, size_t = 0) const noexcept;
|
||||
size_t find(const string_view, size_t = 0) const noexcept;
|
||||
size_t find(string_view, size_t = 0) const noexcept;
|
||||
|
||||
string(string&& s) noexcept : p(s.p), n(s.n), c(s.c)
|
||||
void swap(string& s) noexcept
|
||||
{
|
||||
s.p = nullptr;
|
||||
s.n = 0;
|
||||
s.c = 0;
|
||||
ctl::swap(blob, s.blob);
|
||||
}
|
||||
|
||||
string(string&& s) noexcept
|
||||
{
|
||||
__builtin_memcpy(blob, s.blob, __::string_size);
|
||||
s.set_small_size(0);
|
||||
}
|
||||
|
||||
void clear() noexcept
|
||||
{
|
||||
n = 0;
|
||||
if (isbig()) {
|
||||
big()->n = 0;
|
||||
} else {
|
||||
set_small_size(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return !n;
|
||||
return isbig() ? !big()->n : small()->rem >= __::sso_max;
|
||||
}
|
||||
|
||||
char* data() const noexcept
|
||||
char* data() noexcept
|
||||
{
|
||||
return p;
|
||||
return isbig() ? big()->p : small()->buf;
|
||||
}
|
||||
|
||||
const char* data() const noexcept
|
||||
{
|
||||
return isbig() ? big()->p : small()->buf;
|
||||
}
|
||||
|
||||
size_t size() const noexcept
|
||||
{
|
||||
return n;
|
||||
#if 0
|
||||
if (!isbig() && small()->rem > __::sso_max)
|
||||
__builtin_trap();
|
||||
#endif
|
||||
return isbig() ? big()->n : __::sso_max - small()->rem;
|
||||
}
|
||||
|
||||
size_t length() const noexcept
|
||||
{
|
||||
return n;
|
||||
return size();
|
||||
}
|
||||
|
||||
size_t capacity() const noexcept
|
||||
{
|
||||
return c;
|
||||
#if 0
|
||||
if (isbig() && big()->c <= __::sso_max)
|
||||
__builtin_trap();
|
||||
#endif
|
||||
return isbig() ? __::big_mask & big()->c : __::string_size;
|
||||
}
|
||||
|
||||
iterator begin() noexcept
|
||||
{
|
||||
return p;
|
||||
return data();
|
||||
}
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
return p + n;
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
return p;
|
||||
return data();
|
||||
}
|
||||
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return p + n;
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
char& front()
|
||||
{
|
||||
if (!n)
|
||||
if (!size())
|
||||
__builtin_trap();
|
||||
return p[0];
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
const char& front() const
|
||||
{
|
||||
if (!n)
|
||||
if (!size())
|
||||
__builtin_trap();
|
||||
return p[0];
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
char& back()
|
||||
{
|
||||
if (!n)
|
||||
if (!size())
|
||||
__builtin_trap();
|
||||
return p[n - 1];
|
||||
return data()[size() - 1];
|
||||
}
|
||||
|
||||
const char& back() const
|
||||
{
|
||||
if (!n)
|
||||
if (!size())
|
||||
__builtin_trap();
|
||||
return p[n - 1];
|
||||
return data()[size() - 1];
|
||||
}
|
||||
|
||||
char& operator[](size_t i) noexcept
|
||||
{
|
||||
if (i >= n)
|
||||
if (i >= size())
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
const char& operator[](size_t i) const noexcept
|
||||
const char& operator[](const size_t i) const noexcept
|
||||
{
|
||||
if (i >= n)
|
||||
if (i >= size())
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
void push_back(char ch) noexcept
|
||||
void push_back(const char ch) noexcept
|
||||
{
|
||||
append(ch);
|
||||
}
|
||||
@@ -160,9 +256,9 @@ struct string
|
||||
append(s.p, s.n);
|
||||
}
|
||||
|
||||
inline constexpr operator string_view() const noexcept
|
||||
operator string_view() const noexcept
|
||||
{
|
||||
return string_view(p, n);
|
||||
return string_view(data(), size());
|
||||
}
|
||||
|
||||
string& operator=(const char* s) noexcept
|
||||
@@ -179,7 +275,7 @@ struct string
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& operator+=(char x) noexcept
|
||||
string& operator+=(const char x) noexcept
|
||||
{
|
||||
append(x);
|
||||
return *this;
|
||||
@@ -220,8 +316,76 @@ struct string
|
||||
{
|
||||
return compare(s) >= 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void destroy_big() noexcept;
|
||||
void init_big(const string&) noexcept;
|
||||
void init_big(string_view) noexcept;
|
||||
void init_big(size_t, char) noexcept;
|
||||
|
||||
bool isbig() const noexcept
|
||||
{
|
||||
return *(blob + __::sso_max) & 0x80;
|
||||
}
|
||||
|
||||
void set_small_size(const size_t size) noexcept
|
||||
{
|
||||
if (size > __::sso_max)
|
||||
__builtin_trap();
|
||||
__s.rem = __::sso_max - size;
|
||||
}
|
||||
|
||||
void set_big_string(char* const p, const size_t n, const size_t c2) noexcept
|
||||
{
|
||||
if (c2 > __::big_mask)
|
||||
__builtin_trap();
|
||||
__b.p = p;
|
||||
__b.n = n;
|
||||
__b.c = c2 | ~__::big_mask;
|
||||
}
|
||||
|
||||
__::small_string* small() noexcept
|
||||
{
|
||||
if (isbig())
|
||||
__builtin_trap();
|
||||
return &__s;
|
||||
}
|
||||
|
||||
const __::small_string* small() const noexcept
|
||||
{
|
||||
if (isbig())
|
||||
__builtin_trap();
|
||||
return &__s;
|
||||
}
|
||||
|
||||
__::big_string* big() noexcept
|
||||
{
|
||||
if (!isbig())
|
||||
__builtin_trap();
|
||||
return &__b;
|
||||
}
|
||||
|
||||
const __::big_string* big() const noexcept
|
||||
{
|
||||
if (!isbig())
|
||||
__builtin_trap();
|
||||
return &__b;
|
||||
}
|
||||
|
||||
friend string strcat(string_view, string_view) noexcept;
|
||||
|
||||
union
|
||||
{
|
||||
__::big_string __b;
|
||||
__::small_string __s;
|
||||
char blob[__::string_size];
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(string) == __::string_size);
|
||||
static_assert(sizeof(__::small_string) == __::string_size);
|
||||
static_assert(sizeof(__::big_string) == __::string_size);
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
@@ -233,4 +397,4 @@ operator"" s(const char* s, size_t n)
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_STRING_H_
|
||||
#endif // CTL_STRING_H_
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
@@ -26,7 +26,7 @@
|
||||
namespace ctl {
|
||||
|
||||
size_t
|
||||
string_view::find(char ch, size_t pos) const noexcept
|
||||
string_view::find(const char ch, const size_t pos) const noexcept
|
||||
{
|
||||
char* q;
|
||||
if (n && (q = (char*)memchr(p, ch, n)))
|
||||
@@ -35,7 +35,7 @@ string_view::find(char ch, size_t pos) const noexcept
|
||||
}
|
||||
|
||||
size_t
|
||||
string_view::find(const string_view s, size_t pos) const noexcept
|
||||
string_view::find(const string_view s, const size_t pos) const noexcept
|
||||
{
|
||||
char* q;
|
||||
if (pos > n)
|
||||
@@ -46,7 +46,7 @@ string_view::find(const string_view s, size_t pos) const noexcept
|
||||
}
|
||||
|
||||
string_view
|
||||
string_view::substr(size_t pos, size_t count) const noexcept
|
||||
string_view::substr(const size_t pos, size_t count) const noexcept
|
||||
{
|
||||
size_t last;
|
||||
if (pos > n)
|
||||
|
||||
+17
-16
@@ -1,7 +1,8 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_STRINGVIEW_H_
|
||||
#define COSMOPOLITAN_CTL_STRINGVIEW_H_
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
@@ -28,7 +29,7 @@ struct string_view
|
||||
{
|
||||
}
|
||||
|
||||
constexpr string_view(const char* s, size_t n) noexcept : p(s), n(n)
|
||||
constexpr string_view(const char* s, const size_t n) noexcept : p(s), n(n)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,16 +37,16 @@ struct string_view
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const string_view) const noexcept;
|
||||
bool operator!=(const string_view) const noexcept;
|
||||
bool contains(const string_view) const noexcept;
|
||||
bool ends_with(const string_view) const noexcept;
|
||||
bool starts_with(const string_view) const noexcept;
|
||||
bool operator==(string_view) const noexcept;
|
||||
bool operator!=(string_view) const noexcept;
|
||||
bool contains(string_view) const noexcept;
|
||||
bool ends_with(string_view) const noexcept;
|
||||
bool starts_with(string_view) const noexcept;
|
||||
string_view substr(size_t = 0, size_t = npos) const noexcept;
|
||||
size_t find(char, size_t = 0) const noexcept;
|
||||
size_t find(const string_view, size_t = 0) const noexcept;
|
||||
size_t find(string_view, size_t = 0) const noexcept;
|
||||
|
||||
constexpr string_view& operator=(const string_view& s) noexcept
|
||||
constexpr string_view& operator=(const string_view s) noexcept
|
||||
{
|
||||
p = s.p;
|
||||
n = s.n;
|
||||
@@ -72,14 +73,14 @@ struct string_view
|
||||
return n;
|
||||
}
|
||||
|
||||
constexpr const char& operator[](size_t i) const noexcept
|
||||
constexpr const char& operator[](const size_t i) const noexcept
|
||||
{
|
||||
if (i >= n)
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
}
|
||||
|
||||
constexpr void remove_prefix(size_t count)
|
||||
constexpr void remove_prefix(const size_t count)
|
||||
{
|
||||
if (count > n)
|
||||
__builtin_trap();
|
||||
@@ -87,7 +88,7 @@ struct string_view
|
||||
n -= count;
|
||||
}
|
||||
|
||||
constexpr void remove_suffix(size_t count)
|
||||
constexpr void remove_suffix(const size_t count)
|
||||
{
|
||||
if (count > n)
|
||||
__builtin_trap();
|
||||
@@ -133,22 +134,22 @@ struct string_view
|
||||
return strcmp(*this, s);
|
||||
}
|
||||
|
||||
bool operator<(const string_view& s) const noexcept
|
||||
bool operator<(const string_view s) const noexcept
|
||||
{
|
||||
return compare(s) < 0;
|
||||
}
|
||||
|
||||
bool operator<=(const string_view& s) const noexcept
|
||||
bool operator<=(const string_view s) const noexcept
|
||||
{
|
||||
return compare(s) <= 0;
|
||||
}
|
||||
|
||||
bool operator>(const string_view& s) const noexcept
|
||||
bool operator>(const string_view s) const noexcept
|
||||
{
|
||||
return compare(s) > 0;
|
||||
}
|
||||
|
||||
bool operator>=(const string_view& s) const noexcept
|
||||
bool operator>=(const string_view s) const noexcept
|
||||
{
|
||||
return compare(s) >= 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "unique_ptr.h"
|
||||
@@ -0,0 +1,163 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
||||
#define COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
||||
#include "utility.h"
|
||||
#include <__type_traits/is_convertible.h>
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct default_delete
|
||||
{
|
||||
constexpr default_delete() noexcept = default;
|
||||
template<typename U>
|
||||
constexpr default_delete(default_delete<U>&&) noexcept
|
||||
{
|
||||
}
|
||||
constexpr void operator()(T* const p) const noexcept
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct default_delete<T[]>
|
||||
{
|
||||
constexpr default_delete() noexcept = default;
|
||||
template<typename U>
|
||||
constexpr default_delete(default_delete<U>&&) noexcept
|
||||
{
|
||||
}
|
||||
constexpr void operator()(T* const p) const noexcept
|
||||
{
|
||||
delete[] p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename D = default_delete<T>>
|
||||
struct unique_ptr
|
||||
{
|
||||
using pointer = T*;
|
||||
using element_type = T;
|
||||
using deleter_type = D;
|
||||
|
||||
pointer p;
|
||||
[[no_unique_address]] deleter_type d;
|
||||
|
||||
constexpr unique_ptr(const nullptr_t = nullptr) noexcept : p(nullptr), d()
|
||||
{
|
||||
}
|
||||
|
||||
constexpr unique_ptr(const pointer p) noexcept : p(p), d()
|
||||
{
|
||||
}
|
||||
|
||||
constexpr unique_ptr(const pointer p, auto&& d) noexcept
|
||||
: p(p), d(ctl::forward<decltype(d)>(d))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename U, typename E>
|
||||
requires std::is_convertible_v<U, T> && std::is_convertible_v<E, D>
|
||||
constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept
|
||||
: p(u.p), d(ctl::move(u.d))
|
||||
{
|
||||
u.p = nullptr;
|
||||
}
|
||||
|
||||
unique_ptr(const unique_ptr&) = delete;
|
||||
|
||||
constexpr ~unique_ptr() /* noexcept */
|
||||
{
|
||||
if (p)
|
||||
d(p);
|
||||
}
|
||||
|
||||
constexpr unique_ptr& operator=(unique_ptr r) noexcept
|
||||
{
|
||||
swap(r);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr pointer release() noexcept
|
||||
{
|
||||
pointer r = p;
|
||||
p = nullptr;
|
||||
return r;
|
||||
}
|
||||
|
||||
constexpr void reset(const pointer p2 = pointer()) noexcept
|
||||
{
|
||||
const pointer r = p;
|
||||
p = p2;
|
||||
if (r)
|
||||
d(r);
|
||||
}
|
||||
|
||||
constexpr void swap(unique_ptr& r) noexcept
|
||||
{
|
||||
using ctl::swap;
|
||||
swap(p, r.p);
|
||||
swap(d, r.d);
|
||||
}
|
||||
|
||||
constexpr pointer get() const noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
constexpr deleter_type& get_deleter() noexcept
|
||||
{
|
||||
return d;
|
||||
}
|
||||
|
||||
constexpr const deleter_type& get_deleter() const noexcept
|
||||
{
|
||||
return d;
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
element_type& operator*() const noexcept(noexcept(*ctl::declval<pointer>()))
|
||||
{
|
||||
if (!p)
|
||||
__builtin_trap();
|
||||
return *p;
|
||||
}
|
||||
|
||||
pointer operator->() const noexcept
|
||||
{
|
||||
if (!p)
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
constexpr unique_ptr<T>
|
||||
make_unique(Args&&... args)
|
||||
{
|
||||
return unique_ptr<T>(new T(ctl::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr unique_ptr<T>
|
||||
make_unique_for_overwrite()
|
||||
{
|
||||
#if 0
|
||||
// You'd think that it'd work like this, but std::unique_ptr does not.
|
||||
return unique_ptr<T>(
|
||||
static_cast<T*>(::operator new(sizeof(T), align_val_t(alignof(T)))));
|
||||
#else
|
||||
return unique_ptr<T>(new T);
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO(mrdomino): specializations for T[]
|
||||
|
||||
} // namespace ctl
|
||||
#endif // COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
||||
@@ -0,0 +1,19 @@
|
||||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "utility.h"
|
||||
@@ -0,0 +1,61 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_UTILITY_H_
|
||||
#define COSMOPOLITAN_CTL_UTILITY_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
namespace __ {
|
||||
|
||||
template<typename T>
|
||||
struct no_infer_
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using no_infer = typename no_infer_<T>::type;
|
||||
|
||||
} // namespace __
|
||||
|
||||
template<typename T>
|
||||
constexpr T&&
|
||||
move(T& t) noexcept
|
||||
{
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T&&
|
||||
forward(__::no_infer<T>& t) noexcept
|
||||
{
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
// TODO(mrdomino): requires move_constructible<T> && move_assignable<T>
|
||||
constexpr void
|
||||
swap(T& a, T& b) noexcept
|
||||
{
|
||||
T t(ctl::move(a));
|
||||
a = ctl::move(b);
|
||||
b = ctl::move(t);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
// TODO(mrdomino): requires is_swappable
|
||||
constexpr void
|
||||
swap(T (&a)[N], T (&b)[N]) noexcept
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
swap(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T&&
|
||||
declval() noexcept;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_UTILITY_H_
|
||||
+9
-10
@@ -1,10 +1,9 @@
|
||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=c++ ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#define COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/swap.h>
|
||||
#include "new.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
@@ -172,7 +171,7 @@ struct vector
|
||||
return;
|
||||
T* newP = new T[c2];
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
newP[i] = std::move(p[i]);
|
||||
newP[i] = ctl::move(p[i]);
|
||||
delete[] p;
|
||||
p = newP;
|
||||
c = c2;
|
||||
@@ -196,7 +195,7 @@ struct vector
|
||||
c2 += c2 >> 1;
|
||||
reserve(c2);
|
||||
}
|
||||
new (&p[n]) T(std::forward<T>(e));
|
||||
new (&p[n]) T(ctl::forward<T>(e));
|
||||
++n;
|
||||
}
|
||||
|
||||
@@ -208,7 +207,7 @@ struct vector
|
||||
c2 += c2 >> 1;
|
||||
reserve(c2);
|
||||
}
|
||||
new (&p[n]) T(std::forward<Args>(args)...);
|
||||
new (&p[n]) T(ctl::forward<Args>(args)...);
|
||||
++n;
|
||||
}
|
||||
|
||||
@@ -235,9 +234,9 @@ struct vector
|
||||
|
||||
void swap(vector& other) noexcept
|
||||
{
|
||||
std::swap(n, other.n);
|
||||
std::swap(c, other.c);
|
||||
std::swap(p, other.p);
|
||||
ctl::swap(n, other.n);
|
||||
ctl::swap(c, other.c);
|
||||
ctl::swap(p, other.p);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
__static_yoink("__die");
|
||||
__static_yoink("GetSymbolByAddr");
|
||||
__static_yoink("malloc_inspect_all");
|
||||
|
||||
char *lol(int n) {
|
||||
return malloc(n);
|
||||
}
|
||||
|
||||
char *(*pLol)(int) = lol;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *s = pLol(4);
|
||||
s[4] = 1;
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <sys/auxv.h>
|
||||
#include <sys/socket.h>
|
||||
#include <time.h>
|
||||
#include "libc/mem/leaks.h"
|
||||
|
||||
/**
|
||||
* @fileoverview greenbean lightweight threaded web server
|
||||
@@ -411,7 +412,5 @@ int main(int argc, char *argv[]) {
|
||||
unassert(!pthread_mutex_destroy(&statuslock));
|
||||
|
||||
// quality assurance
|
||||
if (IsModeDbg()) {
|
||||
CheckForMemoryLeaks();
|
||||
}
|
||||
CheckForMemoryLeaks();
|
||||
}
|
||||
+1
-1
@@ -137,7 +137,7 @@ struct Action {
|
||||
|
||||
struct Audio {
|
||||
size_t i;
|
||||
int16_t p[FRAMESIZE];
|
||||
int16_t p[65536];
|
||||
};
|
||||
|
||||
struct Status {
|
||||
|
||||
+7
-7
@@ -3051,7 +3051,7 @@ static const char *updatepwd(const char *dir) {
|
||||
if (*dir != '/') {
|
||||
if (new[-1] != '/')
|
||||
USTPUTC('/', new);
|
||||
if (new > lim &&*lim == '/')
|
||||
if (new > lim && *lim == '/')
|
||||
lim++;
|
||||
} else {
|
||||
USTPUTC('/', new);
|
||||
@@ -8917,7 +8917,7 @@ static int readtoken1(int firstc, char const *syntax, char *eofmark,
|
||||
quotef = 0;
|
||||
bqlist = NULL;
|
||||
STARTSTACKSTR(out);
|
||||
loop : { /* for each line, until end of word */
|
||||
loop: { /* for each line, until end of word */
|
||||
CHECKEND(); /* set c to PEOF if at end of here document */
|
||||
for (;;) { /* until end of line or end of word */
|
||||
CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
|
||||
@@ -9069,7 +9069,7 @@ endword:
|
||||
* is called, c is set to the first character of the next input line. If
|
||||
* we are at the end of the here document, this routine sets the c to PEOF.
|
||||
*/
|
||||
checkend : {
|
||||
checkend: {
|
||||
if (realeofmark(eofmark)) {
|
||||
int markloc;
|
||||
char *p;
|
||||
@@ -9112,7 +9112,7 @@ checkend : {
|
||||
* specifying the fd to be redirected. The variable "c" contains the
|
||||
* first character of the redirection operator.
|
||||
*/
|
||||
parseredir : {
|
||||
parseredir: {
|
||||
char fd = *out;
|
||||
union node *np;
|
||||
np = (union node *)stalloc(sizeof(struct nfile));
|
||||
@@ -9169,7 +9169,7 @@ parseredir : {
|
||||
* Parse a substitution. At this point, we have read the dollar sign
|
||||
* and nothing else.
|
||||
*/
|
||||
parsesub : {
|
||||
parsesub: {
|
||||
int subtype;
|
||||
int typeloc;
|
||||
char *p;
|
||||
@@ -9287,7 +9287,7 @@ parsesub : {
|
||||
* list of commands (passed by reference), and savelen is the number of
|
||||
* characters on the top of the stack which must be preserved.
|
||||
*/
|
||||
parsebackq : {
|
||||
parsebackq: {
|
||||
struct nodelist **nlpp;
|
||||
union node *n;
|
||||
char *str;
|
||||
@@ -9382,7 +9382,7 @@ parsebackq : {
|
||||
/*
|
||||
* Parse an arithmetic expansion (indicate start of one and set state)
|
||||
*/
|
||||
parsearith : {
|
||||
parsearith: {
|
||||
synstack_push(&synstack, synstack->prev ?: alloca(sizeof(*synstack)),
|
||||
ARISYNTAX);
|
||||
synstack->dblquote = 1;
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_ASAN_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_ASAN_INTERNAL_H_
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/asmflag.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
forceinline bool __asan_is_valid_timespec(const struct timespec *ts) {
|
||||
#ifdef __x86_64__
|
||||
bool zf;
|
||||
asm(ZFLAG_ASM("cmpw\t$0,0x7fff8000(%1)")
|
||||
: ZFLAG_CONSTRAINT(zf)
|
||||
: "r"((intptr_t)ts >> 3)
|
||||
: "memory");
|
||||
return zf;
|
||||
#else
|
||||
return __asan_is_valid(ts, sizeof(*ts));
|
||||
#endif
|
||||
}
|
||||
|
||||
forceinline bool __asan_is_valid_timeval(const struct timeval *tv) {
|
||||
return __asan_is_valid_timespec((const struct timespec *)tv);
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_ASAN_INTERNAL_H_ */
|
||||
+1
-2
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/log/log.h"
|
||||
@@ -59,7 +58,7 @@ int chdir(const char *path) {
|
||||
if (_weaken(GetProgramExecutableName)) {
|
||||
_weaken(GetProgramExecutableName)();
|
||||
}
|
||||
if (!path || (IsAsan() && !__asan_is_valid_str(path))) {
|
||||
if (!path) {
|
||||
rc = efault();
|
||||
} else if (_weaken(__zipos_parseuri) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
|
||||
+1
-2
@@ -19,7 +19,6 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
@@ -49,7 +48,7 @@
|
||||
*/
|
||||
int chroot(const char *path) {
|
||||
int rc;
|
||||
if (!path || (IsAsan() && !__asan_is_valid_str(path))) {
|
||||
if (!path) {
|
||||
rc = efault();
|
||||
} else {
|
||||
rc = sys_chroot(path);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/asan.internal.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
@@ -63,7 +62,7 @@ static int sys_clock_getres_xnu(int clock, struct timespec *ts) {
|
||||
*/
|
||||
int clock_getres(int clock, struct timespec *ts) {
|
||||
int rc;
|
||||
if (!ts || (IsAsan() && !__asan_is_valid_timespec(ts))) {
|
||||
if (!ts) {
|
||||
rc = efault();
|
||||
} else if (clock == 127) {
|
||||
rc = einval(); // 127 is used by consts.sh to mean unsupported
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/asan.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
@@ -35,7 +34,7 @@ int clock_settime(int clockid, const struct timespec *ts) {
|
||||
struct timeval tv;
|
||||
if (clockid == 127) {
|
||||
rc = einval(); // 127 is used by consts.sh to mean unsupported
|
||||
} else if (!ts || (IsAsan() && !__asan_is_valid_timespec(ts))) {
|
||||
} else if (!ts) {
|
||||
rc = efault();
|
||||
} else if (IsXnu()) {
|
||||
if (clockid == CLOCK_REALTIME) {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
@@ -109,11 +108,6 @@ ssize_t copy_file_range(int infd, int64_t *opt_in_out_inoffset, int outfd,
|
||||
|
||||
if (!g_copy_file_range.ok) {
|
||||
rc = enosys();
|
||||
} else if (IsAsan() && ((opt_in_out_inoffset &&
|
||||
!__asan_is_valid(opt_in_out_inoffset, 8)) ||
|
||||
(opt_in_out_outoffset &&
|
||||
!__asan_is_valid(opt_in_out_outoffset, 8)))) {
|
||||
rc = efault();
|
||||
} else if (__isfdkind(outfd, kFdZip)) {
|
||||
rc = ebadf();
|
||||
} else if (__isfdkind(infd, kFdZip)) {
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -52,10 +51,8 @@
|
||||
int faccessat(int dirfd, const char *path, int amode, int flags) {
|
||||
int e, rc;
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && !__asan_is_valid_str(path)) {
|
||||
rc = efault();
|
||||
} else if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS)) ||
|
||||
!(amode == F_OK || !(amode & ~(R_OK | W_OK | X_OK)))) {
|
||||
if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS)) ||
|
||||
!(amode == F_OK || !(amode & ~(R_OK | W_OK | X_OK)))) {
|
||||
rc = einval();
|
||||
} else if (__isfdkind(dirfd, kFdZip)) {
|
||||
rc = enotsup();
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -52,10 +51,7 @@ int sys_fchmodat2(int, const char *, unsigned, int);
|
||||
*/
|
||||
int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid_str(path)) {
|
||||
rc = efault();
|
||||
} else if (_weaken(__zipos_notat) &&
|
||||
(rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
if (_weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
rc = erofs();
|
||||
} else if (!IsWindows()) {
|
||||
if (IsLinux() && flags) {
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -43,10 +42,7 @@
|
||||
int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
|
||||
int flags) {
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid_str(path)) {
|
||||
rc = efault();
|
||||
} else if (_weaken(__zipos_notat) &&
|
||||
(rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
if (_weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
rc = erofs();
|
||||
} else {
|
||||
rc = sys_fchownat(dirfd, path, uid, gid, flags);
|
||||
|
||||
@@ -28,11 +28,11 @@
|
||||
#include "libc/calls/wincrash.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/leaky.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/leaks.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
@@ -75,7 +75,7 @@ static textwindows struct FileLock *NewFileLock(void) {
|
||||
fl = g_locks.free;
|
||||
g_locks.free = fl->next;
|
||||
} else {
|
||||
unassert((fl = _weaken(malloc)(sizeof(*fl))));
|
||||
unassert((fl = may_leak(_weaken(malloc)(sizeof(*fl)))));
|
||||
}
|
||||
bzero(fl, sizeof(*fl));
|
||||
fl->next = g_locks.list;
|
||||
@@ -83,8 +83,6 @@ static textwindows struct FileLock *NewFileLock(void) {
|
||||
return fl;
|
||||
}
|
||||
|
||||
IGNORE_LEAKS(NewFileLock)
|
||||
|
||||
static textwindows void FreeFileLock(struct FileLock *fl) {
|
||||
fl->next = g_locks.free;
|
||||
g_locks.free = fl;
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
@@ -32,9 +31,7 @@ int sys_fcntl(int fd, int cmd, uintptr_t arg, int impl(int, int, ...)) {
|
||||
if ((islock = cmd == F_GETLK || //
|
||||
cmd == F_SETLK || //
|
||||
cmd == F_SETLKW)) {
|
||||
if ((!IsAsan() && !arg) ||
|
||||
(IsAsan() &&
|
||||
!__asan_is_valid((struct flock *)arg, sizeof(struct flock)))) {
|
||||
if (!arg) {
|
||||
return efault();
|
||||
}
|
||||
cosmo2flock(arg);
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/files.h"
|
||||
@@ -51,11 +50,8 @@ bool32 fileexists(const char *path) {
|
||||
struct ZiposUri zipname;
|
||||
uint16_t path16[PATH_MAX];
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid_str(path)) {
|
||||
efault();
|
||||
res = false;
|
||||
} else if (_weaken(__zipos_open) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (_weaken(__zipos_open) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (_weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
|
||||
res = true;
|
||||
} else {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "libc/elf/tinyelf.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/directmap.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
+1
-4
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/stat.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -42,9 +41,7 @@
|
||||
*/
|
||||
int fstat(int fd, struct stat *st) {
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(st, sizeof(*st))) {
|
||||
rc = efault();
|
||||
} else if (__isfdkind(fd, kFdZip)) {
|
||||
if (__isfdkind(fd, kFdZip)) {
|
||||
rc = _weaken(__zipos_fstat)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st);
|
||||
} else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -76,10 +75,7 @@ int fstatat(int dirfd, const char *path, struct stat *st, int flags) {
|
||||
// execve() depends on this
|
||||
int rc;
|
||||
struct ZiposUri zipname;
|
||||
if (IsAsan() && (!__asan_is_valid_str(path) || //
|
||||
!__asan_is_valid(st, sizeof(*st)))) {
|
||||
rc = efault();
|
||||
} else if (flags & ~AT_SYMLINK_NOFOLLOW) {
|
||||
if (flags & ~AT_SYMLINK_NOFOLLOW) {
|
||||
return einval();
|
||||
} else if (__isfdkind(dirfd, kFdZip)) {
|
||||
STRACE("zipos dirfd not supported yet");
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/asan.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/groups.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/stdckdint.h"
|
||||
@@ -34,11 +33,7 @@
|
||||
*/
|
||||
int getgroups(int size, uint32_t list[]) {
|
||||
int rc;
|
||||
size_t n;
|
||||
if (IsAsan() &&
|
||||
(ckd_mul(&n, size, sizeof(list[0])) || !__asan_is_valid(list, n))) {
|
||||
rc = efault();
|
||||
} else if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
|
||||
if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
|
||||
rc = sys_getgroups(size, list);
|
||||
} else {
|
||||
rc = enosys();
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/asmflag.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -182,7 +181,7 @@ ssize_t __getrandom(void *p, size_t n, unsigned f) {
|
||||
*/
|
||||
ssize_t getrandom(void *p, size_t n, unsigned f) {
|
||||
ssize_t rc;
|
||||
if ((!p && n) || (IsAsan() && !__asan_is_valid(p, n))) {
|
||||
if ((!p && n)) {
|
||||
rc = efault();
|
||||
} else if (f & ~(GRND_RANDOM | GRND_NONBLOCK)) {
|
||||
rc = einval();
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/struct/rlimit.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
@@ -41,7 +40,7 @@ int getrlimit(int resource, struct rlimit *rlim) {
|
||||
int rc;
|
||||
if (resource == 127) {
|
||||
rc = einval();
|
||||
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
|
||||
} else if (!rlim) {
|
||||
rc = efault();
|
||||
} else if (IsXnuSilicon()) {
|
||||
rc = _sysret(__syslib->__getrlimit(resource, rlim));
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/files.h"
|
||||
@@ -51,11 +50,8 @@ bool32 isdirectory(const char *path) {
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid_str(path)) {
|
||||
efault();
|
||||
res = false;
|
||||
} else if (_weaken(__zipos_open) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (_weaken(__zipos_open) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (_weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
|
||||
res = S_ISDIR(st.cosmo.st_mode);
|
||||
} else {
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
@@ -48,11 +47,8 @@ bool32 isregularfile(const char *path) {
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid_str(path)) {
|
||||
efault();
|
||||
res = false;
|
||||
} else if (_weaken(__zipos_open) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (_weaken(__zipos_open) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (_weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
|
||||
res = !!S_ISREG(st.cosmo.st_mode);
|
||||
} else {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/files.h"
|
||||
@@ -51,11 +50,8 @@ bool32 issymlink(const char *path) {
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid_str(path)) {
|
||||
efault();
|
||||
res = false;
|
||||
} else if (_weaken(__zipos_open) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (_weaken(__zipos_open) &&
|
||||
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
res = false;
|
||||
} else if (IsMetal()) {
|
||||
res = false;
|
||||
|
||||
+3
-7
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -40,12 +39,9 @@
|
||||
int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
|
||||
int flags) {
|
||||
int rc;
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid_str(oldpath) || !__asan_is_valid_str(newpath))) {
|
||||
rc = efault();
|
||||
} else if (_weaken(__zipos_notat) &&
|
||||
((rc = __zipos_notat(olddirfd, oldpath)) == -1 ||
|
||||
(rc = __zipos_notat(newdirfd, newpath)) == -1)) {
|
||||
if (_weaken(__zipos_notat) &&
|
||||
((rc = __zipos_notat(olddirfd, oldpath)) == -1 ||
|
||||
(rc = __zipos_notat(newdirfd, newpath)) == -1)) {
|
||||
STRACE("zipos fchownat not supported yet");
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_linkat(olddirfd, oldpath, newdirfd, newpath, flags);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
@@ -38,9 +37,7 @@
|
||||
*/
|
||||
int madvise(void *addr, size_t length, int advice) {
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(addr, length)) {
|
||||
rc = enomem();
|
||||
} else if (!IsWindows()) {
|
||||
if (!IsWindows()) {
|
||||
rc = sys_madvise(addr, length, advice);
|
||||
} else {
|
||||
rc = sys_madvise_nt(addr, length, advice);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -53,10 +52,7 @@
|
||||
*/
|
||||
int mkdirat(int dirfd, const char *path, unsigned mode) {
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid_str(path)) {
|
||||
rc = efault();
|
||||
} else if (_weaken(__zipos_notat) &&
|
||||
(rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
if (_weaken(__zipos_notat) && (rc = __zipos_notat(dirfd, path)) == -1) {
|
||||
STRACE("zipos mkdirat not supported yet");
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_mkdirat(dirfd, path, mode);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
@@ -42,8 +41,6 @@
|
||||
*/
|
||||
int mknod(const char *path, uint32_t mode, uint64_t dev) {
|
||||
int e, rc;
|
||||
if (IsAsan() && !__asan_is_valid_str(path))
|
||||
return efault();
|
||||
if (mode & S_IFREG)
|
||||
return creat(path, mode & ~S_IFREG);
|
||||
if (mode & S_IFDIR)
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
@@ -96,7 +95,7 @@ textwindows int __mkntpath2(const char *path,
|
||||
// 4. Need ≥13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
|
||||
// which is an "8.3 filename" from the DOS days
|
||||
|
||||
if (!path || (IsAsan() && !__asan_is_valid_str(path))) {
|
||||
if (!path) {
|
||||
return efault();
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -26,7 +26,6 @@
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -180,7 +179,7 @@ int openat(int dirfd, const char *path, int flags, ...) {
|
||||
va_end(va);
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
if (!path || (IsAsan() && !__asan_is_valid_str(path))) {
|
||||
if (!path) {
|
||||
rc = efault();
|
||||
} else if ((flags & O_UNLINK) &&
|
||||
(flags & (O_CREAT | O_EXCL)) != (O_CREAT | O_EXCL)) {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/calls/termios.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/log/rop.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
@@ -94,13 +93,6 @@ int openpty(int *mfd, int *sfd, char *name, //
|
||||
if (IsWindows() || IsMetal()) {
|
||||
return enosys();
|
||||
}
|
||||
if (IsAsan() && (!__asan_is_valid(mfd, sizeof(int)) ||
|
||||
!__asan_is_valid(sfd, sizeof(int)) ||
|
||||
(name && !__asan_is_valid(name, 16)) ||
|
||||
(tio && !__asan_is_valid(tio, sizeof(*tio))) ||
|
||||
(wsz && !__asan_is_valid(wsz, sizeof(*wsz))))) {
|
||||
return efault();
|
||||
}
|
||||
BLOCK_CANCELATION;
|
||||
rc = openpty_impl(mfd, sfd, name, tio, wsz);
|
||||
ALLOW_CANCELATION;
|
||||
|
||||
+1
-2
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
@@ -36,7 +35,7 @@
|
||||
*/
|
||||
int pipe(int pipefd[hasatleast 2]) {
|
||||
int rc;
|
||||
if (!pipefd || (IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2))) {
|
||||
if (!pipefd) {
|
||||
// needed for windows which is polyfilled
|
||||
// needed for xnu and netbsd which don't take an argument
|
||||
rc = efault();
|
||||
|
||||
+1
-3
@@ -19,7 +19,6 @@
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
@@ -44,8 +43,7 @@ int pipe2(int pipefd[hasatleast 2], int flags) {
|
||||
int rc;
|
||||
if (flags & ~(O_CLOEXEC | O_NONBLOCK | (O_DIRECT != -1u ? O_DIRECT : 0))) {
|
||||
return einval();
|
||||
} else if (!pipefd ||
|
||||
(IsAsan() && !__asan_is_valid(pipefd, sizeof(int) * 2))) {
|
||||
} else if (!pipefd) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_pipe2(pipefd, flags);
|
||||
|
||||
+1
-6
@@ -18,7 +18,6 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/cp.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sock/struct/pollfd.h"
|
||||
#include "libc/sock/struct/pollfd.internal.h"
|
||||
@@ -65,13 +64,9 @@
|
||||
*/
|
||||
int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
|
||||
int rc;
|
||||
size_t n;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
if (IsAsan() &&
|
||||
(ckd_mul(&n, nfds, sizeof(struct pollfd)) || !__asan_is_valid(fds, n))) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
if (!IsWindows()) {
|
||||
if (!IsMetal()) {
|
||||
rc = sys_poll(fds, nfds, timeout_ms);
|
||||
} else {
|
||||
|
||||
+1
-8
@@ -23,7 +23,6 @@
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sock/struct/pollfd.h"
|
||||
#include "libc/sock/struct/pollfd.internal.h"
|
||||
@@ -60,18 +59,12 @@
|
||||
*/
|
||||
int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
|
||||
const sigset_t *sigmask) {
|
||||
size_t n;
|
||||
int e, rc;
|
||||
sigset_t oldmask;
|
||||
struct timespec ts, *tsp;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
if (IsAsan() &&
|
||||
(ckd_mul(&n, nfds, sizeof(struct pollfd)) || !__asan_is_valid(fds, n) ||
|
||||
(timeout && !__asan_is_valid(timeout, sizeof(timeout))) ||
|
||||
(sigmask && !__asan_is_valid(sigmask, sizeof(sigmask))))) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
if (!IsWindows()) {
|
||||
e = errno;
|
||||
if (timeout) {
|
||||
ts = *timeout;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/macros.internal.h"
|
||||
@@ -67,8 +66,6 @@ ssize_t pread(int fd, void *buf, size_t size, int64_t offset) {
|
||||
rc = einval();
|
||||
} else if (fd < 0) {
|
||||
rc = ebadf();
|
||||
} else if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
rc = efault();
|
||||
} else if (__isfdkind(fd, kFdZip)) {
|
||||
rc = _weaken(__zipos_read)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle,
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -52,8 +51,6 @@ static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
|
||||
return ebadf();
|
||||
if (iovlen < 0)
|
||||
return einval();
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
|
||||
return efault();
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
@@ -77,13 +76,6 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
BEGIN_CANCELATION_POINT;
|
||||
if (nfds < 0) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() &&
|
||||
((readfds && !__asan_is_valid(readfds, FD_SIZE(nfds))) ||
|
||||
(writefds && !__asan_is_valid(writefds, FD_SIZE(nfds))) ||
|
||||
(exceptfds && !__asan_is_valid(exceptfds, FD_SIZE(nfds))) ||
|
||||
(timeout && !__asan_is_valid(timeout, sizeof(*timeout))) ||
|
||||
(sigmask && !__asan_is_valid(sigmask, sizeof(*sigmask))))) {
|
||||
rc = efault();
|
||||
} else {
|
||||
if (readfds) {
|
||||
old_readfds = *readfds;
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
@@ -62,8 +61,6 @@ ssize_t pwrite(int fd, const void *buf, size_t size, int64_t offset) {
|
||||
rc = einval();
|
||||
} else if (fd == -1) {
|
||||
rc = ebadf();
|
||||
} else if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
rc = efault();
|
||||
} else if (__isfdkind(fd, kFdZip)) {
|
||||
rc = ebadf();
|
||||
} else if (!IsWindows()) {
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -52,8 +51,6 @@ static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
|
||||
return ebadf();
|
||||
if (iovlen < 0)
|
||||
return einval();
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
|
||||
return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)
|
||||
return ebadf();
|
||||
|
||||
|
||||
+1
-2
@@ -23,7 +23,6 @@
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
@@ -74,7 +73,7 @@ ssize_t read(int fd, void *buf, size_t size) {
|
||||
|
||||
if (fd < 0) {
|
||||
rc = ebadf();
|
||||
} else if ((!buf && size) || (IsAsan() && !__asan_is_valid(buf, size))) {
|
||||
} else if ((!buf && size)) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = _weaken(__zipos_read)(
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/zipos.internal.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
@@ -52,8 +52,7 @@
|
||||
*/
|
||||
ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
|
||||
ssize_t bytes;
|
||||
if ((bufsiz && !buf) || (IsAsan() && (!__asan_is_valid_str(path) ||
|
||||
!__asan_is_valid(buf, bufsiz)))) {
|
||||
if ((bufsiz && !buf)) {
|
||||
bytes = efault();
|
||||
} else if (_weaken(__zipos_notat) &&
|
||||
(bytes = __zipos_notat(dirfd, path)) == -1) {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
@@ -49,8 +48,6 @@ static ssize_t readv_impl(int fd, const struct iovec *iov, int iovlen) {
|
||||
return ebadf();
|
||||
if (iovlen < 0)
|
||||
return einval();
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen))
|
||||
return efault();
|
||||
|
||||
// XNU and BSDs will EINVAL if requested bytes exceeds INT_MAX
|
||||
// this is inconsistent with Linux which ignores huge requests
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
@@ -46,12 +45,9 @@
|
||||
int renameat(int olddirfd, const char *oldpath, int newdirfd,
|
||||
const char *newpath) {
|
||||
int rc;
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid_str(oldpath) || !__asan_is_valid_str(newpath))) {
|
||||
rc = efault();
|
||||
} else if (_weaken(__zipos_notat) &&
|
||||
((rc = __zipos_notat(olddirfd, oldpath)) == -1 ||
|
||||
(rc = __zipos_notat(newdirfd, newpath)) == -1)) {
|
||||
if (_weaken(__zipos_notat) &&
|
||||
((rc = __zipos_notat(olddirfd, oldpath)) == -1 ||
|
||||
(rc = __zipos_notat(newdirfd, newpath)) == -1)) {
|
||||
STRACE("zipos renameat not supported yet");
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_renameat(olddirfd, oldpath, newdirfd, newpath);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/sched_param.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
@@ -33,7 +32,7 @@
|
||||
int sched_getparam(int pid, struct sched_param *param) {
|
||||
int rc;
|
||||
struct sched_param p;
|
||||
if (!param || (IsAsan() && !__asan_is_valid(param, sizeof(*param)))) {
|
||||
if (!param) {
|
||||
rc = efault();
|
||||
} else if (IsNetbsd()) {
|
||||
if (!(rc = sys_sched_getscheduler_netbsd(pid, &p))) {
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/sched_param.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
@@ -34,7 +33,7 @@
|
||||
int sched_setparam(int pid, const struct sched_param *param) {
|
||||
int rc, policy;
|
||||
struct sched_param p;
|
||||
if (!param || (IsAsan() && !__asan_is_valid(param, sizeof(*param)))) {
|
||||
if (!param) {
|
||||
rc = efault();
|
||||
} else if (IsNetbsd()) {
|
||||
if ((rc = policy = sys_sched_getscheduler_netbsd(pid, &p)) != -1) {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
@@ -63,12 +62,6 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
BEGIN_CANCELATION_POINT;
|
||||
if (nfds < 0) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() &&
|
||||
((readfds && !__asan_is_valid(readfds, FD_SIZE(nfds))) ||
|
||||
(writefds && !__asan_is_valid(writefds, FD_SIZE(nfds))) ||
|
||||
(exceptfds && !__asan_is_valid(exceptfds, FD_SIZE(nfds))) ||
|
||||
(timeout && !__asan_is_valid(timeout, sizeof(*timeout))))) {
|
||||
rc = efault();
|
||||
} else {
|
||||
if (readfds) {
|
||||
old_readfds = *readfds;
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/groups.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/stdckdint.h"
|
||||
@@ -40,11 +39,7 @@
|
||||
*/
|
||||
int setgroups(size_t size, const uint32_t list[]) {
|
||||
int rc;
|
||||
size_t n;
|
||||
if (IsAsan() &&
|
||||
(ckd_mul(&n, size, sizeof(list[0])) || !__asan_is_valid(list, n))) {
|
||||
rc = efault();
|
||||
} else if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
|
||||
if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
|
||||
rc = sys_setgroups(size, list);
|
||||
} else {
|
||||
rc = enosys();
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "libc/calls/struct/rlimit.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
@@ -80,7 +79,7 @@ int setrlimit(int resource, const struct rlimit *rlim) {
|
||||
int rc;
|
||||
if (resource == 127) {
|
||||
rc = einval();
|
||||
} else if (!rlim || (IsAsan() && !__asan_is_valid(rlim, sizeof(*rlim)))) {
|
||||
} else if (!rlim) {
|
||||
rc = efault();
|
||||
} else if (IsXnuSilicon()) {
|
||||
rc = _sysret(__syslib->__setrlimit(resource, rlim));
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/asan.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/dce.h"
|
||||
@@ -29,7 +28,7 @@
|
||||
*/
|
||||
int settimeofday(const struct timeval *tv, const struct timezone *tz) {
|
||||
int rc;
|
||||
if (!tv || (IsAsan() && !__asan_is_valid_timeval(tv))) {
|
||||
if (!tv) {
|
||||
rc = efault();
|
||||
} else {
|
||||
rc = sys_settimeofday(tv, 0);
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
@@ -167,10 +166,6 @@ static int __sigaction(int sig, const struct sigaction *act,
|
||||
return einval();
|
||||
if (sig == SIGKILL || sig == SIGSTOP)
|
||||
return einval();
|
||||
if (IsAsan() && ((act && !__asan_is_valid(act, sizeof(*act))) ||
|
||||
(oldact && !__asan_is_valid(oldact, sizeof(*oldact))))) {
|
||||
return efault();
|
||||
}
|
||||
if (!act) {
|
||||
rva = (int32_t)(intptr_t)SIG_DFL;
|
||||
} else if ((intptr_t)act->sa_handler < kSigactionMinRva) {
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#include "libc/calls/struct/sigaltstack.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/sysv/consts/ss.h"
|
||||
@@ -129,11 +129,8 @@ static int sigaltstack_bsd(const struct sigaltstack *neu,
|
||||
*/
|
||||
int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) {
|
||||
int rc;
|
||||
if (IsAsan() && ((old && !__asan_is_valid(old, sizeof(*old))) ||
|
||||
(neu && !__asan_is_valid(neu, sizeof(*neu))))) {
|
||||
rc = efault();
|
||||
} else if (neu && ((neu->ss_size >> 32) || //
|
||||
(neu->ss_flags & ~(SS_ONSTACK | SS_DISABLE)))) {
|
||||
if (neu && ((neu->ss_size >> 32) || //
|
||||
(neu->ss_flags & ~(SS_ONSTACK | SS_DISABLE)))) {
|
||||
rc = einval();
|
||||
} else if (neu && neu->ss_size < __get_minsigstksz()) {
|
||||
rc = enomem();
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
@@ -38,7 +37,7 @@
|
||||
*/
|
||||
int sigpending(sigset_t *pending) {
|
||||
int rc;
|
||||
if (!pending || (IsAsan() && !__asan_is_valid(pending, sizeof(*pending)))) {
|
||||
if (!pending) {
|
||||
rc = efault();
|
||||
} else if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) {
|
||||
// 128 signals on NetBSD and FreeBSD, 64 on Linux, 32 on OpenBSD and XNU
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
@@ -48,9 +47,7 @@ int sigsuspend(const sigset_t *ignore) {
|
||||
int rc;
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
if (IsAsan() && ignore && !__asan_is_valid(ignore, sizeof(*ignore))) {
|
||||
rc = efault();
|
||||
} else if (IsXnu() || IsOpenbsd()) {
|
||||
if (IsXnu() || IsOpenbsd()) {
|
||||
// openbsd and xnu use a 32 signal register convention
|
||||
rc = sys_sigsuspend(ignore ? (void *)(intptr_t)(uint32_t)*ignore : 0, 8);
|
||||
} else {
|
||||
|
||||
@@ -17,14 +17,12 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sigtimedwait.h"
|
||||
#include "libc/calls/asan.internal.h"
|
||||
#include "libc/calls/cp.internal.h"
|
||||
#include "libc/calls/sigtimedwait.internal.h"
|
||||
#include "libc/calls/struct/siginfo.internal.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
@@ -52,11 +50,7 @@ int sigtimedwait(const sigset_t *set, siginfo_t *info,
|
||||
union siginfo_meta si = {0};
|
||||
BEGIN_CANCELATION_POINT;
|
||||
|
||||
if (IsAsan() && (!__asan_is_valid(set, sizeof(*set)) ||
|
||||
(info && !__asan_is_valid(info, sizeof(*info))) ||
|
||||
(timeout && !__asan_is_valid_timespec(timeout)))) {
|
||||
rc = efault();
|
||||
} else if (IsLinux() || IsFreebsd() || IsNetbsd()) {
|
||||
if (IsLinux() || IsFreebsd() || IsNetbsd()) {
|
||||
if (timeout) {
|
||||
// 1. Linux needs its size parameter
|
||||
// 2. NetBSD modifies timeout argument
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
@@ -82,11 +81,6 @@ ssize_t splice(int infd, int64_t *opt_in_out_inoffset, int outfd,
|
||||
cosmo_once(&g_splice.once, splice_init);
|
||||
if (!g_splice.ok) {
|
||||
rc = enosys();
|
||||
} else if (IsAsan() && ((opt_in_out_inoffset &&
|
||||
!__asan_is_valid(opt_in_out_inoffset, 8)) ||
|
||||
(opt_in_out_outoffset &&
|
||||
!__asan_is_valid(opt_in_out_outoffset, 8)))) {
|
||||
rc = efault();
|
||||
} else if (__isfdkind(infd, kFdZip) || __isfdkind(outfd, kFdZip)) {
|
||||
rc = enotsup();
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,7 @@ COSMOPOLITAN_C_START_
|
||||
|
||||
#define BPF_MAXINSNS 4096
|
||||
|
||||
#define BPF_CLASS(code) ((code)&0x07)
|
||||
#define BPF_CLASS(code) ((code) & 0x07)
|
||||
#define BPF_LD 0x00 /* load into accumulator */
|
||||
#define BPF_LDX 0x01 /* load into index register */
|
||||
#define BPF_ST 0x02 /* store from immediate */
|
||||
@@ -14,13 +14,13 @@ COSMOPOLITAN_C_START_
|
||||
#define BPF_RET 0x06
|
||||
#define BPF_MISC 0x07
|
||||
|
||||
#define BPF_SIZE(code) ((code)&0x18)
|
||||
#define BPF_SIZE(code) ((code) & 0x18)
|
||||
#define BPF_W 0x00 /* 32-bit */
|
||||
#define BPF_H 0x08 /* 16-bit */
|
||||
#define BPF_B 0x10 /* 8-bit */
|
||||
#define BPF_DW 0x18 /* 64-bit (eBPF only) */
|
||||
|
||||
#define BPF_MODE(code) ((code)&0xe0)
|
||||
#define BPF_MODE(code) ((code) & 0xe0)
|
||||
#define BPF_IMM 0x00 /* 64-bit immediate */
|
||||
#define BPF_ABS 0x20
|
||||
#define BPF_IND 0x40
|
||||
@@ -28,7 +28,7 @@ COSMOPOLITAN_C_START_
|
||||
#define BPF_LEN 0x80
|
||||
#define BPF_MSH 0xa0
|
||||
|
||||
#define BPF_OP(code) ((code)&0xf0)
|
||||
#define BPF_OP(code) ((code) & 0xf0)
|
||||
#define BPF_ADD 0x00
|
||||
#define BPF_SUB 0x10
|
||||
#define BPF_MUL 0x20
|
||||
@@ -41,7 +41,7 @@ COSMOPOLITAN_C_START_
|
||||
#define BPF_MOD 0x90
|
||||
#define BPF_XOR 0xa0
|
||||
|
||||
#define BPF_SRC(code) ((code)&0x08)
|
||||
#define BPF_SRC(code) ((code) & 0x08)
|
||||
#define BPF_JA 0x00
|
||||
#define BPF_JEQ 0x10
|
||||
#define BPF_JGT 0x20
|
||||
@@ -442,7 +442,7 @@ COSMOPOLITAN_C_START_
|
||||
#define BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP (1U << 2)
|
||||
|
||||
#define BPF_LINE_INFO_LINE_NUM(line_col) ((line_col) >> 10)
|
||||
#define BPF_LINE_INFO_LINE_COL(line_col) ((line_col)&0x3ff)
|
||||
#define BPF_LINE_INFO_LINE_COL(line_col) ((line_col) & 0x3ff)
|
||||
|
||||
#define BTF_F_COMPACT (1ULL << 0)
|
||||
#define BTF_F_NONAME (1ULL << 1)
|
||||
|
||||
@@ -17,9 +17,9 @@ struct sock_fprog {
|
||||
const struct sock_filter *filter;
|
||||
};
|
||||
|
||||
#define BPF_RVAL(code) ((code)&0x18)
|
||||
#define BPF_RVAL(code) ((code) & 0x18)
|
||||
#define BPF_A 0x10
|
||||
#define BPF_MISCOP(code) ((code)&0xf8)
|
||||
#define BPF_MISCOP(code) ((code) & 0xf8)
|
||||
#define BPF_TAX 0x00
|
||||
#define BPF_TXA 0x80
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
@@ -41,10 +40,6 @@
|
||||
*/
|
||||
int symlinkat(const char *target, int newdirfd, const char *linkpath) {
|
||||
int rc;
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid_str(target) || !__asan_is_valid_str(linkpath))) {
|
||||
rc = efault();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
rc = sys_symlinkat(target, newdirfd, linkpath);
|
||||
} else {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
#define IsPeek(request) (IsLinux() && (request)-1u < 3)
|
||||
#define IsPeek(request) (IsLinux() && (request) - 1u < 3)
|
||||
|
||||
/**
|
||||
* Traces process.
|
||||
|
||||
Loaded 100 of 513 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user