diff --git a/.gitignore b/.gitignore index 7d5f217e9..764bb43d6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ __pycache__ /TAGS /bx_enh_dbg.ini /tool/emacs/*.elc +/perf.data +/perf.data.old diff --git a/build/functions.mk b/build/functions.mk index 6196802ed..d72556f06 100644 --- a/build/functions.mk +++ b/build/functions.mk @@ -12,5 +12,9 @@ tail = $(wordlist 2,$(words $1),$1) reverse = $(if $1,$(call reverse,$(call tail,$1)) $(firstword $1)) -uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) uniqr = $(if $1,$(call uniqr,$(filter-out $(firstword $1),$1)) $(firstword $1)) + +# polyfill uniq native (landlock make 1.4) +ifneq ($(call uniq,c b c a),c b a) +uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) +endif diff --git a/libc/stdio/fgets_unlocked.c b/libc/stdio/fgets_unlocked.c index 9870a22b0..de4c94ef8 100644 --- a/libc/stdio/fgets_unlocked.c +++ b/libc/stdio/fgets_unlocked.c @@ -16,8 +16,12 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/dce.h" #include "libc/errno.h" +#include "libc/intrin/kprintf.h" +#include "libc/macros.internal.h" #include "libc/stdio/stdio.h" +#include "libc/str/str.h" /** * Reads line from stream. @@ -33,20 +37,33 @@ * zero characters have been read */ char *fgets_unlocked(char *s, int size, FILE *f) { - int c; - char *p; + int c, n; + char *p, *b, *t; p = s; if (size > 0) { while (--size > 0) { - if ((c = fgetc_unlocked(f)) == -1) { - if (ferror_unlocked(f) == EINTR) { - continue; - } else { - break; + if (!IsTiny() && f->beg < f->end) { + b = f->buf + f->beg; + n = MIN(f->end - f->beg, size); + if ((t = memchr(b, '\n', n))) { + n = t + 1 - b; } + memcpy(p, b, n); + f->beg += n; + size -= n - 1; + p += n; + if (t) break; + } else { + if ((c = fgetc_unlocked(f)) == -1) { + if (ferror_unlocked(f) == EINTR) { + continue; + } else { + break; + } + } + *p++ = c & 255; + if (c == '\n') break; } - *p++ = c & 255; - if (c == '\n') break; } *p = '\0'; } diff --git a/test/libc/stdio/fgets_test.c b/test/libc/stdio/fgets_test.c index 91d658c4d..37b7fb0eb 100644 --- a/test/libc/stdio/fgets_test.c +++ b/test/libc/stdio/fgets_test.c @@ -19,6 +19,7 @@ #include "libc/mem/mem.h" #include "libc/runtime/gc.internal.h" #include "libc/stdio/stdio.h" +#include "libc/testlib/ezbench.h" #include "libc/testlib/hyperion.h" #include "libc/testlib/testlib.h" @@ -31,3 +32,19 @@ TEST(fgets, test) { ASSERT_STREQ("John Keats\n", fgets(buf, sizeof(buf), f)); fclose(f); } + +void Benchmark(void) { + FILE *f; + char *line; + char buf[512]; + f = fmemopen(gc(strdup(kHyperion)), kHyperionSize, "r+"); + for (;;) { + line = fgets(buf, sizeof(buf), f); + if (!line) break; + } + fclose(f); +} + +BENCH(fgets, bench) { + EZBENCH2("fgets", donothing, Benchmark()); +} diff --git a/third_party/make/commands.c b/third_party/make/commands.c index eb361b212..3ac7c9b49 100644 --- a/third_party/make/commands.c +++ b/third_party/make/commands.c @@ -520,6 +520,7 @@ fatal_error_signal (int sig) if (sig == SIGTERM || sig == SIGINT || sig == SIGHUP || sig == SIGQUIT + || sig == SIGPIPE ) { struct child *c; diff --git a/third_party/make/expand.c b/third_party/make/expand.c index 7ab3674f9..713acd6a9 100644 --- a/third_party/make/expand.c +++ b/third_party/make/expand.c @@ -441,7 +441,8 @@ expand_argument (const char *str, const char *end) r = allocated_variable_expand (tmp); - free (alloc); + if (alloc) + free (alloc); return r; } diff --git a/third_party/make/function.c b/third_party/make/function.c index da5fd1815..e2240bbaf 100644 --- a/third_party/make/function.c +++ b/third_party/make/function.c @@ -23,6 +23,9 @@ this program. If not, see . */ #include "third_party/make/job.h" #include "third_party/make/os.h" #include "third_party/make/commands.h" +#include "libc/mem/critbit0.h" +#include "libc/log/rop.h" +#include "libc/runtime/runtime.h" #include "third_party/make/debug.h" struct function_table_entry @@ -1160,6 +1163,45 @@ func_sort (char *o, char **argv, const char *funcname UNUSED) return o; } +/* + chop argv[0] into words, and remove duplicates. + */ +static char * +func_uniq (char *o, char **argv, const char *funcname UNUSED) +{ + char *p; + size_t len; + int mutated; + bool once = false; + const char *s = argv[0]; + struct critbit0 t = {0}; + + while ((p = find_next_token (&s, &len))) + { + ++s; + p[len] = 0; + RETURN_ON_ERROR ((mutated = critbit0_insert (&t, p))); + if (mutated) + { + if (once) + o = variable_buffer_output (o, " ", 1); + else + once = true; + o = variable_buffer_output (o, p, len); + } + } + + critbit0_clear (&t); + + return o; + +OnError: + critbit0_clear (&t); + OSS (error, NILF, "%s: function failed: %s", + "uniq", strerror (errno)); + exit (1); +} + /* $(if condition,true-part[,false-part]) @@ -2137,6 +2179,7 @@ static struct function_table_entry function_table_init[] = FT_ENTRY ("value", 0, 1, 1, func_value), FT_ENTRY ("eval", 0, 1, 1, func_eval), FT_ENTRY ("file", 1, 2, 1, func_file), + FT_ENTRY ("uniq", 0, 1, 1, func_uniq), #ifdef EXPERIMENTAL FT_ENTRY ("eq", 2, 2, 1, func_eq), FT_ENTRY ("not", 0, 1, 1, func_not),