Brush up some more code

This commit is contained in:
Justine Tunney 2023-07-10 10:16:55 -07:00
parent ee6566a152
commit a2d269dc38
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
32 changed files with 251 additions and 335 deletions

Binary file not shown.

Binary file not shown.

View file

@ -220,7 +220,7 @@ int unbing(int c) {
l = 0;
r = ARRAYLEN(kCp437i) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if ((kCp437i[m] >> 8) < c) {
l = m + 1;
} else if ((kCp437i[m] >> 8) > c) {

View file

@ -743,7 +743,7 @@ static void __asan_report_memory_origin_image(intptr_t a, int z) {
r = n = st->count;
k = a - st->addr_base;
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (st->symbols[m].y < k) {
l = m + 1;
} else {

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/intrin/midpoint.h"
#include "libc/runtime/memtrack.internal.h"
noasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
@ -25,7 +24,7 @@ noasan unsigned FindMemoryInterval(const struct MemoryIntervals *mm, int x) {
l = 0;
r = mm->i;
while (l < r) {
m = _midpoint(l, r);
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (mm->p[m].y < x) {
l = m + 1;
} else {

View file

@ -161,7 +161,7 @@ privileged static bool kismapped(int x) {
if (kismemtrackhosed()) return false;
r = _weaken(_mmi)->i;
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (_weaken(_mmi)->p[m].y < x) {
l = m + 1;
} else {

View file

@ -1,32 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_BITS_MIDPOINT_H_
#define COSMOPOLITAN_LIBC_BITS_MIDPOINT_H_
#include "libc/assert.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86__)
/**
* Computes `(a + b) / 2` assuming unsigned.
*
* This implementation is the fastest on AMD Zen architecture.
*/
#define _midpoint(a, b) \
({ \
typeof((a) + (b)) a_ = (a); \
typeof(a_) b_ = (b); \
_unassert(a_ >= 0); \
_unassert(b_ >= 0); \
asm("add\t%1,%0\n\t" \
"rcr\t%0" \
: "+r"(a_) \
: "r"(b_)); \
a_; \
})
#else
/**
* Computes `(a + b) / 2` assuming unsigned.
*/
#define _midpoint(a, b) (((a) & (b)) + ((a) ^ (b)) / 2)
#endif /* __GNUC__ && !__STRICT_ANSI__ && x86 */
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_BITS_MIDPOINT_H_ */

View file

@ -18,7 +18,6 @@
*/
#include "libc/assert.h"
#include "libc/dce.h"
#include "libc/intrin/midpoint.h"
#include "libc/mem/mem.h"
#include "libc/mem/sortedints.internal.h"
#include "libc/str/str.h"
@ -28,7 +27,7 @@ bool ContainsInt(const struct SortedInts *t, int k) {
l = 0;
r = t->n - 1;
while (l <= r) {
m = _midpoint(l, r);
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (t->p[m] < k) {
l = m + 1;
} else if (t->p[m] > k) {
@ -45,7 +44,7 @@ int LeftmostInt(const struct SortedInts *t, int k) {
l = 0;
r = t->n;
while (l < r) {
m = _midpoint(l, r);
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (t->p[m] < k) {
l = m + 1;
} else {

View file

@ -41,7 +41,7 @@ dontinstrument privileged int __get_symbol(struct SymbolTable *t, intptr_t a) {
r = n = t->count;
k = a - t->addr_base;
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (t->symbols[m].y < k) {
l = m + 1;
} else {

View file

@ -30,7 +30,8 @@ textwindows int sys_closesocket_nt(struct Fd *fd) {
struct SockFd *sockfd;
sockfd = (struct SockFd *)fd->extra;
free(sockfd);
if (__sys_closesocket_nt(fd->handle) != -1) {
int rc = __sys_closesocket_nt(fd->handle);
if (rc != -1) {
return 0;
} else {
return __winsockerr();

View file

@ -39,7 +39,7 @@ uint32_t crc32c(uint32_t init, const void *data, size_t size) {
static uint32_t kCrc32cTab[256];
if (!once) {
crc32init(kCrc32cTab, 0x82f63b78);
once = 0;
once = 1;
}
p = data;
pe = p + size;

View file

@ -399,7 +399,7 @@ int iswseparator(wint_t c) {
l = 0;
r = n = sizeof(kCodes) / sizeof(kCodes[0]);
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kCodes[m][1] < c) {
l = m + 1;
} else {
@ -411,7 +411,7 @@ int iswseparator(wint_t c) {
l = 0;
r = n = sizeof(kAstralCodes) / sizeof(kAstralCodes[0]);
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kAstralCodes[m][1] < c) {
l = m + 1;
} else {

View file

@ -24,39 +24,6 @@
* 1. If SRC is too long, it's truncated and *not* NUL-terminated.
* 2. If SRC is too short, the remainder is zero-filled.
*
* Please note this function isn't designed to prevent untrustworthy
* data from modifying memory without authorization; the memccpy()
* function can be used for that purpose.
*
* Here's an example of the only use case we know of for strncpy:
*
* static const struct People {
* char name[8];
* int age;
* } kPeople[] = {
* {"alice", 29}, //
* {"bob", 42}, //
* };
*
* int GetAge(const char *name) {
* char k[8];
* int m, l, r;
* l = 0;
* r = ARRAYLEN(kPeople) - 1;
* strncpy(k, name, 8);
* while (l <= r) {
* m = (l + r) >> 1;
* if (READ64BE(kPeople[m].name) < READ64BE(k)) {
* l = m + 1;
* } else if (READ64BE(kPeople[m].name) > READ64BE(k)) {
* r = m - 1;
* } else {
* return kPeople[m].age;
* }
* }
* return -1;
* }
*
* @return dest
* @see stpncpy(), memccpy()
* @asyncsignalsafe

View file

@ -201,7 +201,7 @@ wint_t towlower(wint_t c) {
l = 0;
r = n = sizeof(kLower) / sizeof(kLower[0]);
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kLower[m].y < c) {
l = m + 1;
} else {
@ -218,7 +218,7 @@ wint_t towlower(wint_t c) {
l = 0;
r = n = sizeof(kAstralLower) / sizeof(kAstralLower[0]);
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kAstralLower[m][1] < c) {
l = m + 1;
} else {

View file

@ -164,7 +164,7 @@ wint_t towupper(wint_t c) {
l = 0;
r = n = sizeof(kUpper) / sizeof(kUpper[0]);
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kUpper[m].y < c) {
l = m + 1;
} else {
@ -181,7 +181,7 @@ wint_t towupper(wint_t c) {
l = 0;
r = n = sizeof(kAstralUpper) / sizeof(kAstralUpper[0]);
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kAstralUpper[m][1] < c) {
l = m + 1;
} else {

View file

@ -119,7 +119,7 @@ static const char *BisectContentType(uint64_t ext) {
l = 0;
r = ARRAYLEN(kContentTypeExtension) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
c = CompareInts(READ64BE(kContentTypeExtension[m].ext), ext);
if (c < 0) {
l = m + 1;

View file

@ -100,7 +100,7 @@ const char *GetHttpReason(int code) {
l = 0;
r = ARRAYLEN(kHttpReason) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kHttpReason[m].code < code) {
l = m + 1;
} else if (kHttpReason[m].code > code) {

View file

@ -43,7 +43,7 @@ static bool BisectNoCompressExts(uint64_t ext) {
l = 0;
r = ARRAYLEN(kNoCompressExts) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (READ64BE(kNoCompressExts[m]) < ext) {
l = m + 1;
} else if (READ64BE(kNoCompressExts[m]) > ext) {

View file

@ -28,7 +28,6 @@
#include "libc/fmt/itoa.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/midpoint.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/mem/mem.h"
#include "libc/mem/sortedints.internal.h"

View file

@ -20,7 +20,6 @@
#include "libc/calls/struct/sched_param.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/midpoint.h"
#include "libc/limits.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/sched.h"
@ -67,7 +66,8 @@ TEST(sched_setscheduler, test) {
TEST(sched_setscheduler, testMidpoint) {
if (!CanTuneRealtimeSchedulers()) return;
struct sched_param p = {_midpoint(sched_get_priority_min(SCHED_FIFO),
sched_get_priority_max(SCHED_FIFO))};
struct sched_param p = {(sched_get_priority_min(SCHED_FIFO) +
sched_get_priority_max(SCHED_FIFO)) /
2};
EXPECT_SYS(0, DEFAULT_POLICY, sched_setscheduler(0, SCHED_FIFO, &p));
}

View file

@ -1894,7 +1894,7 @@ static bool Prefix(struct As *a, const char *p, int n) {
l = 0;
r = ARRAYLEN(kPrefix) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
y = READ64BE(kPrefix[m]);
if (x < y) {
r = m - 1;
@ -1919,7 +1919,7 @@ static bool FindReg(const char *p, int n, struct Reg *out_reg) {
l = 0;
r = ARRAYLEN(kRegs) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
y = READ64BE(kRegs[m].s);
if (x < y) {
r = m - 1;
@ -3740,7 +3740,7 @@ static bool OnDirective8(struct As *a, struct Slice s) {
l = 0;
r = ARRAYLEN(kDirective8) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
y = READ64BE(kDirective8[m].s);
if (x < y) {
r = m - 1;
@ -3763,7 +3763,7 @@ static bool OnDirective16(struct As *a, struct Slice s) {
l = 0;
r = ARRAYLEN(kDirective16) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
y = READ128BE(kDirective16[m].s);
if (x < y) {
r = m - 1;

View file

@ -313,7 +313,7 @@ static unsigned GetMirror(const unsigned short A[][2], size_t n, unsigned c) {
l = 0;
r = n - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (A[m][0] < c) {
l = m + 1;
} else if (A[m][0] > c) {

View file

@ -244,7 +244,7 @@ const char *GetMetroName(int code) {
l = 0;
r = ARRAYLEN(kMetroNames) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kMetroNames[m].code < code) {
l = m + 1;
} else if (kMetroNames[m].code > code) {

View file

@ -3901,7 +3901,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 c)
l = 0;
r = sizeof(kNumericCodes) / sizeof(kNumericCodes[0]) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kNumericCodes[m] < c) {
l = m + 1;
} else if (kNumericCodes[m] > c) {
@ -3914,7 +3914,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 c)
l = 0;
r = sizeof(kNumericAstralCodes) / sizeof(kNumericAstralCodes[0]) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kNumericAstralCodes[m] < c) {
l = m + 1;
} else if (kNumericAstralCodes[m] > c) {

View file

@ -456,7 +456,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 c)
l = 0;
r = sizeof(kNumericCodes) / sizeof(kNumericCodes[0]) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kNumericCodes[m] < c) {
l = m + 1;
} else if (kNumericCodes[m] > c) {
@ -469,7 +469,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 c)
l = 0;
r = sizeof(kNumericAstralCodes) / sizeof(kNumericAstralCodes[0]) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kNumericAstralCodes[m] < c) {
l = m + 1;
} else if (kNumericAstralCodes[m] > c) {

View file

@ -414,7 +414,7 @@ IsIgnoredModule(const char *s)
l = 0;
r = ARRAYLEN(kIgnoredModules) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
x = strcmp(s, kIgnoredModules[m]);
if (x < 0) {
r = m - 1;

View file

@ -25,6 +25,7 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "third_party/stb/stb_truetype.h"
#include "libc/assert.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/likely.h"
@ -34,7 +35,6 @@
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "third_party/stb/stb_rect_pack.h"
#include "third_party/stb/stb_truetype.h"
asm(".ident\t\"\\n\\n\
stb_truetype (MIT License)\\n\
@ -1562,7 +1562,7 @@ static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1
r = ttUSHORT(data+10) - 1;
needle = glyph1 << 16 | glyph2;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
straw = ttULONG(data+18+(m*6)); // note: unaligned read
if (needle < straw)
r = m - 1;
@ -1586,7 +1586,7 @@ static int32_t stbtt__GetCoverageIndex(uint8_t *coverageTable, int glyph)
while (l <= r) {
uint8_t *glyphArray = coverageTable + 4;
uint16_t glyphID;
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
glyphID = ttUSHORT(glyphArray + 2 * m);
straw = glyphID;
if (needle < straw)
@ -1607,7 +1607,7 @@ static int32_t stbtt__GetCoverageIndex(uint8_t *coverageTable, int glyph)
int strawStart, strawEnd, needle=glyph;
while (l <= r) {
uint8_t *rangeRecord;
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
rangeRecord = rangeArray + 6 * m;
strawStart = ttUSHORT(rangeRecord);
strawEnd = ttUSHORT(rangeRecord + 2);
@ -1648,7 +1648,7 @@ static int32_t stbtt__GetGlyphClass(uint8_t *classDefTable, int glyph)
int strawStart, strawEnd, needle=glyph;
while (l <= r) {
uint8_t *classRangeRecord;
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
classRangeRecord = classRangeRecords + 6 * m;
strawStart = ttUSHORT(classRangeRecord);
strawEnd = ttUSHORT(classRangeRecord + 2);
@ -1719,7 +1719,7 @@ static int32_t stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int gl
while (l <= r) {
uint16_t secondGlyph;
uint8_t *pairValue;
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
secondGlyph = ttUSHORT(pairValue);
straw = secondGlyph;

View file

@ -228,6 +228,7 @@ const char *const kGccOnlyFlags[] = {
"-fdelete-dead-exceptions",
"-femit-struct-debug-baseonly",
"-ffp-int-builtin-inexact",
"-finline-functions-called-once",
"-fipa-pta",
"-fivopts",
"-flimit-function-alignment",
@ -241,6 +242,7 @@ const char *const kGccOnlyFlags[] = {
"-fno-fp-int-builtin-inexact",
"-fno-gnu-unique",
"-fno-gnu-unique",
"-fno-inline-functions-called-once",
"-fno-instrument-functions",
"-fno-schedule-insns2",
"-fno-whole-program",
@ -371,7 +373,7 @@ bool IsSafeEnv(const char *s) {
l = 0;
r = ARRAYLEN(kSafeEnv) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
x = strncmp(s, kSafeEnv[m], n);
if (x < 0) {
r = m - 1;
@ -389,7 +391,7 @@ bool IsGccOnlyFlag(const char *s) {
l = 0;
r = ARRAYLEN(kGccOnlyFlags) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
x = strcmp(s, kGccOnlyFlags[m]);
if (x < 0) {
r = m - 1;
@ -1034,7 +1036,6 @@ int main(int argc, char *argv[]) {
#ifdef __x86_64__
} else if (!strcmp(argv[i], "-march=native")) {
struct X86ProcessorModel *model;
if (X86_HAVE(ABM)) AddArg("-mabm");
if (X86_HAVE(XOP)) AddArg("-mxop");
if (X86_HAVE(SSE4A)) AddArg("-msse4a");
if (X86_HAVE(SSE3)) AddArg("-msse3");

View file

@ -13,45 +13,24 @@
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.
TORTIOUS ACTION, ARISING OUTPATH OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/alg.h"
#include "libc/mem/alloca.h"
#include "libc/mem/arraylist.internal.h"
#include "libc/mem/arraylist2.internal.h"
#include "libc/mem/bisectcarleft.internal.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/stdio/append.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/clone.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/thread/spawn.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "libc/thread/wait0.internal.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "third_party/getopt/getopt.internal.h"
#include "tool/build/lib/getargs.h"
@ -73,27 +52,15 @@
*
*/
#define VERSION \
"cosmopolitan mkdeps v2.0\n" \
"copyright 2023 justine tunney\n" \
"https://github.com/jart/cosmopolitan\n"
#define kIncludePrefix "include \""
#define THREADS 1 // _getcpucount()
#define LOCK (void) // if (__threaded) pthread_spin_lock
#define UNLOCK (void) // pthread_spin_unlock
const char kSourceExts[][5] = {".s", ".S", ".c", ".cc", ".cpp"};
const char *const kIgnorePrefixes[] = {
#if 0
"libc/sysv/consts/", "libc/sysv/calls/", "libc/nt/kernel32/",
"libc/nt/KernelBase/", "libc/nt/advapi32/", "libc/nt/gdi32/",
"libc/nt/ntdll/", "libc/nt/user32/", "libc/nt/shell32/",
#endif
};
struct Strings {
size_t i, n;
char *p;
};
struct Source {
unsigned hash;
unsigned name;
@ -120,31 +87,71 @@ struct Edges {
struct Edge *p;
};
char *out;
char **bouts;
pthread_t *th;
unsigned counter;
struct GetArgs ga;
struct Edges edges;
struct Sauce *sauces;
struct Strings strings;
struct Sources sources;
const char *buildroot;
pthread_spinlock_t galock;
pthread_spinlock_t readlock;
pthread_spinlock_t writelock;
pthread_spinlock_t reportlock;
static char *names;
static unsigned counter;
static const char *prog;
static struct Edges edges;
static struct Sauce *sauces;
static struct Sources sources;
static const char *buildroot;
static const char *outpath;
unsigned Hash(const void *s, size_t l) {
return max(1, crc32c(0, s, l));
static wontreturn void Die(const char *reason) {
tinyprint(2, prog, ": ", reason, "\n", NULL);
exit(1);
}
unsigned FindFirstFromEdge(unsigned id) {
static wontreturn void DieSys(const char *thing) {
perror(thing);
exit(1);
}
static wontreturn void DieOom(void) {
Die("out of memory");
}
static unsigned Hash(const void *s, size_t l) {
unsigned h;
h = crc32c(0, s, l);
if (!h) h = 1;
return h;
}
static void *Malloc(size_t n) {
void *p;
if (!(p = malloc(n))) DieOom();
return p;
}
static void *Calloc(size_t n, size_t z) {
void *p;
if (!(p = calloc(n, z))) DieOom();
return p;
}
static void *Realloc(void *p, size_t n) {
if (!(p = realloc(p, n))) DieOom();
return p;
}
static void Appendw(char **b, uint64_t w) {
if (appendw(b, w) == -1) DieOom();
}
static void Appends(char **b, const char *s) {
if (appends(b, s) == -1) DieOom();
}
static void Appendd(char **b, const void *p, size_t n) {
if (appendd(b, p, n) == -1) DieOom();
}
static unsigned FindFirstFromEdge(unsigned id) {
unsigned m, l, r;
l = 0;
r = edges.i;
while (l < r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (edges.p[m].from < id) {
l = m + 1;
} else {
@ -154,9 +161,18 @@ unsigned FindFirstFromEdge(unsigned id) {
return l;
}
void Crunch(void) {
static void AppendEdge(struct Edges *edges, unsigned to, unsigned from) {
if (edges->i + 1 > edges->n) {
edges->n += 1;
edges->n += edges->n >> 1;
edges->p = Realloc(edges->p, edges->n * sizeof(*edges->p));
}
edges->p[edges->i++] = (struct Edge){to, from};
}
static void Crunch(void) {
size_t i, j;
sauces = malloc(sizeof(*sauces) * sources.n);
sauces = Malloc(sizeof(*sauces) * sources.n);
for (j = i = 0; i < sources.n; ++i) {
if (sources.p[i].hash) {
sauces[j].name = sources.p[i].name;
@ -167,16 +183,18 @@ void Crunch(void) {
free(sources.p);
sources.p = 0;
sources.i = j;
_longsort((const long *)sauces, sources.i);
_longsort((const long *)edges.p, edges.i);
if (!radix_sort_int64((const long *)sauces, sources.i) ||
!radix_sort_int64((const long *)edges.p, edges.i)) {
DieOom();
}
}
void Rehash(void) {
static void Rehash(void) {
size_t i, j, step;
struct Sources old;
memcpy(&old, &sources, sizeof(sources));
sources.n = sources.n ? sources.n << 1 : 16;
sources.p = calloc(sources.n, sizeof(struct Source));
sources.p = Calloc(sources.n, sizeof(struct Source));
for (i = 0; i < old.n; ++i) {
if (!old.p[i].hash) continue;
step = 0;
@ -189,9 +207,9 @@ void Rehash(void) {
free(old.p);
}
unsigned GetSourceId(const char *name, size_t len) {
size_t i, step;
static unsigned GetSourceId(const char *name, size_t len) {
unsigned hash;
size_t i, step;
i = 0;
hash = Hash(name, len);
if (sources.n) {
@ -199,7 +217,7 @@ unsigned GetSourceId(const char *name, size_t len) {
do {
i = (hash + step * (step + 1) / 2) & (sources.n - 1);
if (sources.p[i].hash == hash &&
!memcmp(name, &strings.p[sources.p[i].name], len)) {
!memcmp(name, names + sources.p[i].name, len)) {
return sources.p[i].id;
}
step++;
@ -214,142 +232,128 @@ unsigned GetSourceId(const char *name, size_t len) {
} while (sources.p[i].hash);
}
sources.p[i].hash = hash;
sources.p[i].name = CONCAT(&strings.p, &strings.i, &strings.n, name, len);
strings.p[strings.i++] = '\0';
sources.p[i].name = appendz(names).i;
Appendd(&names, name, len);
Appendw(&names, 0);
return (sources.p[i].id = counter++);
}
bool ShouldSkipSource(const char *src) {
unsigned j;
for (j = 0; j < ARRAYLEN(kIgnorePrefixes); ++j) {
if (_startswith(src, kIgnorePrefixes[j])) {
return true;
}
}
return false;
}
wontreturn void OnMissingFile(const char *list, const char *src) {
kprintf("%s is missing\n", src);
DCHECK_EQ(ENOENT, errno, "%s", src);
/*
* This code helps GNU Make automatically fix itself when we
* delete a source file. It removes o/.../srcs.txt or
* o/.../hdrs.txt and exits nonzero. Since we use hyphen
* notation on mkdeps related rules, the build will
* automatically restart itself.
*/
if (list) {
kprintf("%s %s...\n", "Refreshing", list);
unlink(list);
}
exit(1);
}
void *LoadRelationshipsWorker(void *arg) {
static void LoadRelationships(int argc, char *argv[]) {
int fd;
char *map;
ssize_t rc;
bool skipme;
struct stat st;
struct Edge edge;
struct GetArgs ga;
size_t i, n, size, inclen;
unsigned srcid, dependency;
char *buf, srcbuf[PATH_MAX];
const char *p, *pe, *src, *path, *pathend;
getargs_init(&ga, argv + optind);
inclen = strlen(kIncludePrefix);
for (;;) {
LOCK(&galock);
if ((src = getargs_next(&ga))) strcpy(srcbuf, src);
UNLOCK(&galock);
if (!src) break;
src = srcbuf;
if (ShouldSkipSource(src)) continue;
while ((src = getargs_next(&ga))) {
n = strlen(src);
LOCK(&readlock);
srcid = GetSourceId(src, n);
UNLOCK(&readlock);
if ((fd = open(src, O_RDONLY)) == -1) {
LOCK(&reportlock);
OnMissingFile(ga.path, src);
if (errno == ENOENT && ga.path) {
// This code helps GNU Make automatically fix itself when we
// delete a source file. It removes o/.../srcs.txt or
// o/.../hdrs.txt and exits nonzero. Since we use hyphen
// notation on mkdeps related rules, the build will
// automatically restart itself.
tinyprint(2, prog, ": deleting ", ga.path, " to refresh build...\n",
NULL);
}
DieSys(src);
}
CHECK_NE(-1, fstat(fd, &st));
if ((size = st.st_size)) {
CHECK_NE(MAP_FAILED, (buf = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)));
for (p = buf + 1, pe = buf + size; p < pe; ++p) {
if ((rc = lseek(fd, 0, SEEK_END)) == -1) {
DieSys(src);
}
if ((size = rc)) {
map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
DieSys(src);
}
for (p = map + 1, pe = map + size; p < pe; ++p) {
if (!(p = memmem(p, pe - p, kIncludePrefix, inclen))) break;
path = p + inclen;
pathend = memchr(path, '"', pe - path);
if (pathend && //
(p[-1] == '#' || p[-1] == '.') && //
(p - buf == 1 || p[-2] == '\n')) { //
LOCK(&readlock);
(p - map == 1 || p[-2] == '\n')) { //
dependency = GetSourceId(path, pathend - path);
UNLOCK(&readlock);
edge.from = srcid;
edge.to = dependency;
LOCK(&writelock);
append(&edges, &edge);
UNLOCK(&writelock);
AppendEdge(&edges, dependency, srcid);
p = pathend;
}
}
munmap(buf, size);
}
close(fd);
}
return 0;
}
void LoadRelationships(int argc, char *argv[]) {
int i;
getargs_init(&ga, argv + optind);
if (THREADS == 1) {
LoadRelationshipsWorker((void *)(intptr_t)0);
} else {
for (i = 0; i < THREADS; ++i) {
if (pthread_create(th + i, 0, LoadRelationshipsWorker,
(void *)(intptr_t)i)) {
LOCK(&reportlock);
kprintf("error: _spawn(%d) failed %m\n", i);
exit(1);
if (munmap(map, size)) {
DieSys(src);
}
}
for (i = 0; i < THREADS; ++i) {
pthread_join(th[i], 0);
if (close(fd)) {
DieSys(src);
}
}
getargs_destroy(&ga);
}
void GetOpts(int argc, char *argv[]) {
static wontreturn void ShowUsage(int rc, int fd) {
tinyprint(fd, VERSION,
"\n"
"USAGE\n"
"\n",
" ", prog, " -r o// -o OUTPUT INPUT...\n",
"\n"
"FLAGS\n"
"\n"
" -h show usage\n"
" -o OUTPUT set output path\n"
" -r ROOT set build output prefix, e.g. o//\n"
"\n"
"ARGUMENTS\n"
"\n"
" OUTPUT shall be makefile code\n"
" INPUT should be source or @args.txt\n"
"\n",
NULL);
exit(rc);
}
static void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "ho:r:")) != -1) {
while ((opt = getopt(argc, argv, "hno:r:")) != -1) {
switch (opt) {
case 'o':
out = optarg;
outpath = optarg;
break;
case 'r':
buildroot = optarg;
break;
case 'n':
exit(0);
case 'h':
ShowUsage(0, 1);
default:
kprintf("%s: %s [-r %s] [-o %s] [%s...]\n", "Usage", argv[0],
"BUILDROOT", "OUTPUT", "PATHSFILE");
exit(1);
ShowUsage(1, 2);
}
}
if (isempty(out)) kprintf("need -o FILE"), exit(1);
if (isempty(buildroot)) kprintf("need -r o/$(MODE)"), exit(1);
if (!outpath) {
Die("need output path");
}
if (!buildroot) {
Die("need build output prefix");
}
if (optind == argc) {
Die("missing input argument");
}
}
const char *StripExt(char pathbuf[PATH_MAX], const char *s) {
static const char *StripExt(char pathbuf[PATH_MAX + 1], const char *s) {
static char *dot;
strcpy(pathbuf, s);
strlcpy(pathbuf, s, PATH_MAX + 1);
dot = strrchr(pathbuf, '.');
if (dot) *dot = '\0';
return pathbuf;
}
bool IsObjectSource(const char *name) {
static bool IsObjectSource(const char *name) {
int i;
for (i = 0; i < ARRAYLEN(kSourceExts); ++i) {
if (_endswith(name, kSourceExts[i])) return true;
@ -357,7 +361,7 @@ bool IsObjectSource(const char *name) {
return false;
}
forceinline bool Bts(uint32_t *p, size_t i) {
__funline bool Bts(uint32_t *p, size_t i) {
bool r;
uint32_t k;
k = 1u << (i & 31);
@ -366,95 +370,74 @@ forceinline bool Bts(uint32_t *p, size_t i) {
return false;
}
size_t GetFileSizeOrZero(const char *path) {
struct stat st;
st.st_size = 0;
stat(path, &st);
return st.st_size;
}
void Dive(char **bout, uint32_t *visited, unsigned id) {
static void Dive(char **makefile, uint32_t *visited, unsigned id) {
int i;
for (i = FindFirstFromEdge(id); i < edges.i && edges.p[i].from == id; ++i) {
if (Bts(visited, edges.p[i].to)) continue;
appendw(bout, READ32LE(" \\\n\t"));
appends(bout, strings.p + sauces[edges.p[i].to].name);
Dive(bout, visited, edges.p[i].to);
Appendw(makefile, READ32LE(" \\\n\t"));
Appends(makefile, names + sauces[edges.p[i].to].name);
Dive(makefile, visited, edges.p[i].to);
}
}
void *Diver(void *arg) {
char *bout = 0;
static char *Explore(void) {
const char *path;
uint32_t *visited;
unsigned *visited;
size_t i, visilen;
char pathbuf[PATH_MAX];
int x = (intptr_t)arg;
char *makefile = 0;
char buf[PATH_MAX + 1];
visilen = (sources.i + sizeof(*visited) * CHAR_BIT - 1) /
(sizeof(*visited) * CHAR_BIT);
visited = malloc(visilen * sizeof(*visited));
for (i = x; i < sources.i; i += THREADS) {
path = strings.p + sauces[i].name;
visited = Malloc(visilen * sizeof(*visited));
for (i = 0; i < sources.i; ++i) {
path = names + sauces[i].name;
if (!IsObjectSource(path)) continue;
appendw(&bout, '\n');
Appendw(&makefile, '\n');
if (!_startswith(path, "o/")) {
appends(&bout, buildroot);
Appends(&makefile, buildroot);
}
appends(&bout, StripExt(pathbuf, path));
appendw(&bout, READ64LE(".o: \\\n\t"));
appends(&bout, path);
Appends(&makefile, StripExt(buf, path));
Appendw(&makefile, READ64LE(".o: \\\n\t"));
Appends(&makefile, path);
bzero(visited, visilen * sizeof(*visited));
Bts(visited, i);
Dive(&bout, visited, i);
appendw(&bout, '\n');
Dive(&makefile, visited, i);
Appendw(&makefile, '\n');
}
Appendw(&makefile, '\n');
free(visited);
appendw(&bout, '\n');
bouts[x] = bout;
return 0;
}
void Explore(void) {
int i;
if (THREADS == 1) {
Diver((void *)(intptr_t)0);
} else {
for (i = 0; i < THREADS; ++i) {
if (pthread_create(th + i, 0, Diver, (void *)(intptr_t)i)) {
LOCK(&reportlock);
kprintf("error: _spawn(%d) failed %m\n", i);
exit(1);
}
}
for (i = 0; i < THREADS; ++i) {
pthread_join(th[i], 0);
}
}
return makefile;
}
int main(int argc, char *argv[]) {
int i, fd;
int fd;
ssize_t rc;
size_t i, n;
char *makefile;
#ifndef NDEBUG
ShowCrashReports();
if (argc == 2 && !strcmp(argv[1], "-n")) exit(0);
#endif
prog = argv[0];
if (!prog) prog = "mkdeps";
GetOpts(argc, argv);
th = calloc(THREADS, sizeof(*th));
bouts = calloc(THREADS, sizeof(*bouts));
LoadRelationships(argc, argv);
Crunch();
Explore();
CHECK_NE(-1, (fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0644)),
"open(%#s)", out);
for (i = 0; i < THREADS; ++i) {
CHECK_NE(-1, xwrite(fd, bouts[i], appendz(bouts[i]).i));
makefile = Explore();
if ((fd = open(outpath, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) {
DieSys(outpath);
}
CHECK_NE(-1, close(fd));
for (i = 0; i < THREADS; ++i) {
free(bouts[i]);
n = appendz(makefile).i;
for (i = 0; i < n; i += (size_t)rc) {
if ((rc = write(fd, makefile + i, n - i)) == -1) {
DieSys(outpath);
}
}
free(strings.p);
if (close(fd)) {
DieSys(outpath);
}
free(makefile);
free(edges.p);
free(sauces);
free(bouts);
free(th);
free(names);
return 0;
}

View file

@ -550,7 +550,7 @@ static struct Symbol *BisectSymbol(struct Package *pkg, const char *name) {
l = 0;
r = pkg->symbols.i - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
c = strcmp(pkg->strings.p + pkg->symbols.p[m].name, name);
if (c < 0) {
l = m + 1;

View file

@ -669,7 +669,7 @@ static long FindRedirect(const char *s, size_t n) {
l = 0;
r = redirects.n - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
c = CompareSlices(redirects.p[m].path.s, redirects.p[m].path.n, s, n);
if (c < 0) {
l = m + 1;
@ -5381,7 +5381,7 @@ static bool ShouldAutocomplete(const char *s) {
l = 0;
r = ARRAYLEN(kDontAutoComplete) - 1;
while (l <= r) {
m = (l + r) >> 1;
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
c = strcmp(kDontAutoComplete[m], s);
if (c < 0) {
l = m + 1;

View file

@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/midpoint.h"
#include "libc/macros.internal.h"
#include "tool/plinko/lib/char.h"
@ -315,7 +314,7 @@ pureconst bool IsWide(int c) {
l = 0;
r = n = sizeof(kWides) / sizeof(kWides[0]);
while (l < r) {
m = _midpoint(l, r);
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kWides[m][1] < c) {
l = m + 1;
} else {
@ -327,7 +326,7 @@ pureconst bool IsWide(int c) {
l = 0;
r = n = sizeof(kAstralWides) / sizeof(kAstralWides[0]);
while (l < r) {
m = _midpoint(l, r);
m = (l & r) + ((l ^ r) >> 1); // floor((a+b)/2)
if (kAstralWides[m][1] < c) {
l = m + 1;
} else {