mirror of
				https://github.com/jart/cosmopolitan.git
				synced 2025-10-27 03:16:44 +00:00 
			
		
		
		
	Remove some dead code
This commit is contained in:
		
							parent
							
								
									168d1c157e
								
							
						
					
					
						commit
						73c0faa1b5
					
				
					 66 changed files with 324 additions and 7705 deletions
				
			
		|  | @ -3,8 +3,7 @@ | ||||||
| #if !(__ASSEMBLER__ + __LINKER__ + 0) | #if !(__ASSEMBLER__ + __LINKER__ + 0) | ||||||
| COSMOPOLITAN_C_START_ | COSMOPOLITAN_C_START_ | ||||||
| 
 | 
 | ||||||
| extern bool __assert_disable; | void __assert_fail(const char *, const char *, int) relegated; | ||||||
| void __assert_fail(const char *, const char *, int) _Hide relegated; |  | ||||||
| 
 | 
 | ||||||
| #ifdef NDEBUG | #ifdef NDEBUG | ||||||
| #define assert(x) ((void)0) | #define assert(x) ((void)0) | ||||||
|  | @ -16,6 +15,8 @@ void __assert_fail(const char *, const char *, int) _Hide relegated; | ||||||
| #define static_assert _Static_assert | #define static_assert _Static_assert | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef COSMO | ||||||
|  | extern bool __assert_disable; | ||||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||||
| #define _unassert(x) __assert_macro(x, #x) | #define _unassert(x) __assert_macro(x, #x) | ||||||
| #define _npassert(x) __assert_macro(x, #x) | #define _npassert(x) __assert_macro(x, #x) | ||||||
|  | @ -42,7 +43,8 @@ void __assert_fail(const char *, const char *, int) _Hide relegated; | ||||||
|     }                                \ |     }                                \ | ||||||
|     (void)0;                         \ |     (void)0;                         \ | ||||||
|   }) |   }) | ||||||
| #endif | #endif /* NDEBUG */ | ||||||
|  | #endif /* COSMO */ | ||||||
| 
 | 
 | ||||||
| COSMOPOLITAN_C_END_ | COSMOPOLITAN_C_END_ | ||||||
| #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ | #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | │ Copyright 2023 Justine Alexandra Roberts Tunney                              │ | ||||||
| │                                                                              │ | │                                                                              │ | ||||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | │ any purpose with or without fee is hereby granted, provided that the         │ | ||||||
|  | @ -16,18 +16,19 @@ | ||||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||||
|  | #include "libc/assert.h" | ||||||
| #include "libc/calls/calls.h" | #include "libc/calls/calls.h" | ||||||
| #include "libc/elf/struct/ehdr.h" | #include "libc/fmt/itoa.h" | ||||||
| #include "libc/runtime/runtime.h" | #include "libc/runtime/runtime.h" | ||||||
| #include "libc/sysv/consts/auxv.h" |  | ||||||
| 
 | 
 | ||||||
| noasan int main(int argc, char *argv[]) { | /**
 | ||||||
|   int i = 0; |  * Handles assert() failure. | ||||||
|   Elf64_Ehdr *ehdr; |  */ | ||||||
|   ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR); | void __assert_fail(const char *expr, const char *file, int line) { | ||||||
|   if (isatty(1)) exit(1); |   char ibuf[12]; | ||||||
|   for (;;) { |   if (!__assert_disable) { | ||||||
|     write(1, ((char *)ehdr) + i++, 1); |     FormatInt32(ibuf, line); | ||||||
|  |     tinyprint(2, file, ":", ibuf, ": assert(", expr, ") failed\n", NULL); | ||||||
|  |     abort(); | ||||||
|   } |   } | ||||||
|   return 0; |  | ||||||
| } | } | ||||||
|  | @ -62,7 +62,7 @@ COSMOPOLITAN_C_START_ | ||||||
| 
 | 
 | ||||||
| typedef int sig_atomic_t; | typedef int sig_atomic_t; | ||||||
| 
 | 
 | ||||||
| bool32 isatty(int) nosideeffect; | bool32 isatty(int); | ||||||
| char *get_current_dir_name(void) dontdiscard; | char *get_current_dir_name(void) dontdiscard; | ||||||
| char *getcwd(char *, size_t); | char *getcwd(char *, size_t); | ||||||
| char *realpath(const char *, char *); | char *realpath(const char *, char *); | ||||||
|  |  | ||||||
|  | @ -24,11 +24,8 @@ | ||||||
| /**
 | /**
 | ||||||
|  * Writes error messages to standard error. |  * Writes error messages to standard error. | ||||||
|  */ |  */ | ||||||
| void perror(const char *message) { | void perror(const char *thing) { | ||||||
|   int err; |   const char *reason; | ||||||
|   const char *estr; |   if (!(reason = _strerdoc(errno))) reason = "Unknown error"; | ||||||
|   estr = _strerdoc(errno); |   tinyprint(2, thing ? thing : "", thing ? ": " : "", reason, "\n", NULL); | ||||||
|   if (!message) message = ""; |  | ||||||
|   if (!estr) estr = "Unknown error"; |  | ||||||
|   tinyprint(2, message, *message ? ": " : "", estr, "\n", NULL); |  | ||||||
| } | } | ||||||
|  | @ -17,7 +17,7 @@ | ||||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||||
| 
 | 
 | ||||||
| // stub version of abort() for low-dependency apps
 | // stub version of abort() to keep the build a dag
 | ||||||
| __attribute__((__noreturn__, __weak__)) void abort(void) { | __attribute__((__noreturn__, __weak__)) void abort(void) { | ||||||
|   __builtin_trap(); |   __builtin_trap(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||||
| │ Copyright 2021 Justine Alexandra Roberts Tunney                              │ | │ Copyright 2023 Justine Alexandra Roberts Tunney                              │ | ||||||
| │                                                                              │ | │                                                                              │ | ||||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | │ any purpose with or without fee is hereby granted, provided that the         │ | ||||||
|  | @ -16,19 +16,9 @@ | ||||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||||
| #include "libc/fmt/conv.h" |  | ||||||
| #include "libc/math.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) { | // stub version of assert() to keep the build a dag
 | ||||||
|   int i, x, y; | __attribute__((__weak__)) void __assert_fail(const char *expr, const char *file, | ||||||
|   for (i = 1; i < argc; ++i) { |                                              int line) { | ||||||
|     x = atoi(argv[i]); |   __builtin_trap(); | ||||||
|     y = round( |  | ||||||
|         (1.923 * cbrt(x * log(2)) * cbrt(log(x * log(2)) * log(x * log(2))) - |  | ||||||
|          4.69) / |  | ||||||
|         log(2)); |  | ||||||
|     printf("%4d %4d\n", x, y); |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } | } | ||||||
|  | @ -1,33 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/assert.h" |  | ||||||
| #include "libc/atomic.h" |  | ||||||
| #include "libc/intrin/atomic.h" |  | ||||||
| #include "libc/intrin/kprintf.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| 
 |  | ||||||
| privileged void __assert_fail(const char *expr, const char *file, int line) { |  | ||||||
|   static atomic_bool once; |  | ||||||
|   if (!__assert_disable) { |  | ||||||
|     if (!atomic_exchange(&once, true)) { |  | ||||||
|       kprintf("%s:%d: assert(%s) failed (tid %P) %m\n", file, line, expr); |  | ||||||
|     } |  | ||||||
|     __builtin_trap(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| #ifndef COSMOPOLITAN_LIBC_ISYSTEM_ALLOCA_H_ | #ifndef _ALLOCA_H | ||||||
| #define COSMOPOLITAN_LIBC_ISYSTEM_ALLOCA_H_ | #define _ALLOCA_H | ||||||
| #include "libc/mem/alloca.h" | #include "libc/mem/alloca.h" | ||||||
| #endif /* COSMOPOLITAN_LIBC_ISYSTEM_ALLOCA_H_ */ | #endif /* _ALLOCA_H */ | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| #ifndef COSMOPOLITAN_LIBC_ISYSTEM_AR_H_ | #ifndef _AR_H | ||||||
| #define COSMOPOLITAN_LIBC_ISYSTEM_AR_H_ | #define _AR_H | ||||||
| #include "libc/ar.h" | #include "libc/ar.h" | ||||||
| #endif /* COSMOPOLITAN_LIBC_ISYSTEM_AR_H_ */ | #endif /* _AR_H */ | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| #ifndef COSMOPOLITAN_LIBC_ISYSTEM_COSMO_H_ | #ifndef _COSMO_H | ||||||
| #define COSMOPOLITAN_LIBC_ISYSTEM_COSMO_H_ | #define _COSMO_H | ||||||
| 
 | 
 | ||||||
| #ifdef COSMO | #ifdef COSMO | ||||||
| #define COSMO_ALREADY_DEFINED | #define COSMO_ALREADY_DEFINED | ||||||
|  | @ -65,4 +65,4 @@ | ||||||
| #undef COSMO | #undef COSMO | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #endif /* COSMOPOLITAN_LIBC_ISYSTEM_COSMO_H_ */ | #endif /* _COSMO_H */ | ||||||
|  |  | ||||||
|  | @ -1,8 +1,6 @@ | ||||||
| #ifndef COSMOPOLITAN_LIBC_MEM_ALLOCA_H_ | #ifndef COSMOPOLITAN_LIBC_MEM_ALLOCA_H_ | ||||||
| #define COSMOPOLITAN_LIBC_MEM_ALLOCA_H_ | #define COSMOPOLITAN_LIBC_MEM_ALLOCA_H_ | ||||||
| #if !(__ASSEMBLER__ + __LINKER__ + 0) |  | ||||||
| 
 | 
 | ||||||
| #define alloca(size) __builtin_alloca(size) | #define alloca(size) __builtin_alloca(size) | ||||||
| 
 | 
 | ||||||
| #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ |  | ||||||
| #endif /* COSMOPOLITAN_LIBC_MEM_ALLOCA_H_ */ | #endif /* COSMOPOLITAN_LIBC_MEM_ALLOCA_H_ */ | ||||||
|  |  | ||||||
|  | @ -153,7 +153,7 @@ textstartup void cosmo(long *sp, struct Syslib *m1) { | ||||||
|   __envp = envp; |   __envp = envp; | ||||||
|   __auxv = auxv; |   __auxv = auxv; | ||||||
|   environ = envp; |   environ = envp; | ||||||
|   if (argc) program_invocation_name = argv[0]; |   program_invocation_name = argv[0]; | ||||||
| 
 | 
 | ||||||
|   // initialize program
 |   // initialize program
 | ||||||
|   _init(); |   _init(); | ||||||
|  |  | ||||||
|  | @ -60,8 +60,8 @@ | ||||||
|               ? __ckd_##op##ll((__ckd_dword *)(res), (x), (y))           \ |               ? __ckd_##op##ll((__ckd_dword *)(res), (x), (y))           \ | ||||||
|               : __ckd_trap())) |               : __ckd_trap())) | ||||||
| 
 | 
 | ||||||
| __funline wontreturn int __ckd_trap(void) { | __funline int __ckd_trap(void) { | ||||||
|   *(volatile int *)0 = 0; |   return *(volatile int *)0 = 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  |  | ||||||
|  | @ -240,9 +240,10 @@ static int __fmt_ntoa_format(int out(const char *, void *, size_t), void *arg, | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int ntoa2(int out(const char *, void *, size_t), void *arg, | static int __fmt_ntoa2(int out(const char *, void *, size_t), void *arg, | ||||||
|                  uint128_t value, bool neg, unsigned log2base, unsigned prec, |                        uint128_t value, bool neg, unsigned log2base, | ||||||
|                  unsigned width, unsigned flags, const char *alphabet) { |                        unsigned prec, unsigned width, unsigned flags, | ||||||
|  |                        const char *alphabet) { | ||||||
|   uint128_t remainder; |   uint128_t remainder; | ||||||
|   unsigned len, count, digit; |   unsigned len, count, digit; | ||||||
|   char buf[BUFFER_SIZE]; |   char buf[BUFFER_SIZE]; | ||||||
|  | @ -314,7 +315,7 @@ static int __fmt_ntoa(int out(const char *, void *, size_t), void *arg, | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return ntoa2(out, arg, value, neg, log2base, prec, width, flags, lang); |   return __fmt_ntoa2(out, arg, value, neg, log2base, prec, width, flags, lang); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
							
								
								
									
										124
									
								
								third_party/getopt/getopt.c
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										124
									
								
								third_party/getopt/getopt.c
									
										
									
									
										vendored
									
									
								
							|  | @ -41,56 +41,27 @@ getopt (BSD-3)\\n\ | ||||||
| Copyright 1987, 1993, 1994 The Regents of the University of California\""); | Copyright 1987, 1993, 1994 The Regents of the University of California\""); | ||||||
| asm(".include \"libc/disclaimer.inc\""); | asm(".include \"libc/disclaimer.inc\""); | ||||||
| 
 | 
 | ||||||
| #define BADCH  (int)'?' | #define BADCH  '?' | ||||||
| #define BADARG (int)':' | #define BADARG ':' | ||||||
| 
 | 
 | ||||||
| /**
 | int opterr;    // If error message should be printed.
 | ||||||
|  * If error message should be printed. | int optind;    // Index into parent argv vector.
 | ||||||
|  * @see getopt() | int optopt;    // Character checked for validity.
 | ||||||
|  */ | int optreset;  // Reset getopt.
 | ||||||
| int opterr; | char *optarg;  // Argument associated with option.
 | ||||||
| 
 | 
 | ||||||
| /**
 | static struct { | ||||||
|  * Index into parent argv vector. |   char once; | ||||||
|  * @see getopt() |   char emsg[1]; | ||||||
|  */ |   char *place; | ||||||
| int optind; | } optglob; | ||||||
| 
 | 
 | ||||||
| /**
 | static void getopt_print(const char *s) { | ||||||
|  * Character checked for validity. |   const char *prog; | ||||||
|  * @see getopt() |   char b[8] = " -- ?\n"; | ||||||
|  */ |   prog = program_invocation_short_name; | ||||||
| int optopt; |   b[4] = optopt; | ||||||
| 
 |   tinyprint(2, prog ? prog : "", prog ? ": " : "", s, b, NULL); | ||||||
| /**
 |  | ||||||
|  * Reset getopt. |  | ||||||
|  * @see getopt() |  | ||||||
|  */ |  | ||||||
| int optreset; |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Argument associated with option. |  | ||||||
|  * @see getopt() |  | ||||||
|  */ |  | ||||||
| char *optarg; |  | ||||||
| 
 |  | ||||||
| char *getopt_place; |  | ||||||
| static char kGetoptEmsg[1]; |  | ||||||
| 
 |  | ||||||
| static void getopt_print_badch(const char *s) { |  | ||||||
|   char b1[512]; |  | ||||||
|   char b2[8] = " -- "; |  | ||||||
|   b1[0] = 0; |  | ||||||
|   if (program_invocation_name) { |  | ||||||
|     strlcat(b1, program_invocation_name, sizeof(b1)); |  | ||||||
|     strlcat(b1, ": ", sizeof(b1)); |  | ||||||
|   } |  | ||||||
|   strlcat(b1, s, sizeof(b1)); |  | ||||||
|   b2[4] = optopt; |  | ||||||
|   b2[5] = '\n'; |  | ||||||
|   b2[6] = 0; |  | ||||||
|   strlcat(b1, b2, sizeof(b1)); |  | ||||||
|   write(2, b1, strlen(b1)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -116,69 +87,74 @@ static void getopt_print_badch(const char *s) { | ||||||
|  */ |  */ | ||||||
| int getopt(int nargc, char *const nargv[], const char *ostr) { | int getopt(int nargc, char *const nargv[], const char *ostr) { | ||||||
|   char *oli; /* option letter list index */ |   char *oli; /* option letter list index */ | ||||||
|   static bool once; |   if (!optglob.once) { | ||||||
|   if (!once) { |  | ||||||
|     opterr = 1; |     opterr = 1; | ||||||
|     optind = 1; |     optind = 1; | ||||||
|     getopt_place = kGetoptEmsg; |     optglob.place = optglob.emsg; | ||||||
|     once = true; |     optglob.once = 1; | ||||||
|   } |   } | ||||||
|   /*
 |   /*
 | ||||||
|    * Some programs like cvs expect optind = 0 to trigger |    * Some programs like cvs expect optind = 0 to trigger | ||||||
|    * a reset of getopt. |    * a reset of getopt. | ||||||
|    */ |    */ | ||||||
|   if (optind == 0) optind = 1; |   if (!optind) optind = 1; | ||||||
|   if (optreset || *getopt_place == 0) { /* update scanning pointer */ |   if (optreset || !*optglob.place) { /* update scanning pointer */ | ||||||
|     optreset = 0; |     optreset = 0; | ||||||
|     getopt_place = nargv[optind]; |     optglob.place = nargv[optind]; | ||||||
|     if (optind >= nargc || *getopt_place++ != '-') { |     if (optind >= nargc || *optglob.place++ != '-') { | ||||||
|       /* Argument is absent or is not an option */ |       /* Argument is absent or is not an option */ | ||||||
|       getopt_place = kGetoptEmsg; |       optglob.place = optglob.emsg; | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|     optopt = *getopt_place++; |     optopt = *optglob.place++; | ||||||
|     if (optopt == '-' && *getopt_place == 0) { |     if (optopt == '-' && !*optglob.place) { | ||||||
|       /* "--" => end of options */ |       /* "--" => end of options */ | ||||||
|       ++optind; |       ++optind; | ||||||
|       getopt_place = kGetoptEmsg; |       optglob.place = optglob.emsg; | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|     if (optopt == 0) { |     if (!optopt) { | ||||||
|       /* Solitary '-', treat as a '-' option
 |       /* Solitary '-', treat as a '-' option
 | ||||||
|          if the program (eg su) is looking for it. */ |          if the program (eg su) is looking for it. */ | ||||||
|       getopt_place = kGetoptEmsg; |       optglob.place = optglob.emsg; | ||||||
|       if (strchr(ostr, '-') == NULL) return -1; |       if (!strchr(ostr, '-')) return -1; | ||||||
|       optopt = '-'; |       optopt = '-'; | ||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     optopt = *getopt_place++; |     optopt = *optglob.place++; | ||||||
|   } |   } | ||||||
|   /* See if option letter is one the caller wanted... */ |   /* See if option letter is one the caller wanted... */ | ||||||
|   if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) { |   if (optopt == ':' || !(oli = strchr(ostr, optopt))) { | ||||||
|     if (*getopt_place == 0) ++optind; |     if (!*optglob.place) ++optind; | ||||||
|     if (opterr && *ostr != ':') getopt_print_badch("illegal option"); |     if (opterr && *ostr != ':') { | ||||||
|  |       getopt_print("illegal option"); | ||||||
|  |     } | ||||||
|     return BADCH; |     return BADCH; | ||||||
|   } |   } | ||||||
|   /* Does this option need an argument? */ |   /* Does this option need an argument? */ | ||||||
|   if (oli[1] != ':') { |   if (oli[1] != ':') { | ||||||
|     /* don't need argument */ |     /* don't need argument */ | ||||||
|     optarg = NULL; |     optarg = 0; | ||||||
|     if (*getopt_place == 0) ++optind; |     if (!*optglob.place) ++optind; | ||||||
|   } else { |   } else { | ||||||
|     /* Option-argument is either the rest of this argument or the
 |     /* Option-argument is either the rest of this argument or the
 | ||||||
|        entire next argument. */ |        entire next argument. */ | ||||||
|     if (*getopt_place) { |     if (*optglob.place) { | ||||||
|       optarg = getopt_place; |       optarg = optglob.place; | ||||||
|     } else if (nargc > ++optind) { |     } else if (nargc > ++optind) { | ||||||
|       optarg = nargv[optind]; |       optarg = nargv[optind]; | ||||||
|     } else { |     } else { | ||||||
|       /* option-argument absent */ |       /* option-argument absent */ | ||||||
|       getopt_place = kGetoptEmsg; |       optglob.place = optglob.emsg; | ||||||
|       if (*ostr == ':') return BADARG; |       if (*ostr == ':') { | ||||||
|       if (opterr) getopt_print_badch("option requires an argument"); |         return BADARG; | ||||||
|  |       } | ||||||
|  |       if (opterr) { | ||||||
|  |         getopt_print("option requires an argument"); | ||||||
|  |       } | ||||||
|       return BADCH; |       return BADCH; | ||||||
|     } |     } | ||||||
|     getopt_place = kGetoptEmsg; |     optglob.place = optglob.emsg; | ||||||
|     ++optind; |     ++optind; | ||||||
|   } |   } | ||||||
|   return optopt; /* return option letter */ |   return optopt; /* return option letter */ | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								third_party/musl/crypt.internal.h
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								third_party/musl/crypt.internal.h
									
										
									
									
										vendored
									
									
								
							|  | @ -4,11 +4,11 @@ | ||||||
| #if !(__ASSEMBLER__ + __LINKER__ + 0) | #if !(__ASSEMBLER__ + __LINKER__ + 0) | ||||||
| COSMOPOLITAN_C_START_ | COSMOPOLITAN_C_START_ | ||||||
| 
 | 
 | ||||||
| _Hide char *__crypt_des(const char *, const char *, char *); | char *__crypt_des(const char *, const char *, char *); | ||||||
| _Hide char *__crypt_md5(const char *, const char *, char *); | char *__crypt_md5(const char *, const char *, char *); | ||||||
| _Hide char *__crypt_blowfish(const char *, const char *, char *); | char *__crypt_blowfish(const char *, const char *, char *); | ||||||
| _Hide char *__crypt_sha256(const char *, const char *, char *); | char *__crypt_sha256(const char *, const char *, char *); | ||||||
| _Hide char *__crypt_sha512(const char *, const char *, char *); | char *__crypt_sha512(const char *, const char *, char *); | ||||||
| 
 | 
 | ||||||
| COSMOPOLITAN_C_END_ | COSMOPOLITAN_C_END_ | ||||||
| #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ | #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								third_party/nsync/panic.c
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								third_party/nsync/panic.c
									
										
									
									
										vendored
									
									
								
							|  | @ -23,9 +23,6 @@ | ||||||
| 
 | 
 | ||||||
| /* Aborts after printing the nul-terminated string s[]. */ | /* Aborts after printing the nul-terminated string s[]. */ | ||||||
| void nsync_panic_ (const char *s) { | void nsync_panic_ (const char *s) { | ||||||
| 	char b[256], *p = b; | 	tinyprint (2, "nsync panic: ", s, NULL); | ||||||
| 	p = stpcpy (p, "panic: "); |  | ||||||
| 	p = stpcpy (p, s); |  | ||||||
| 	write (2, b, p - b); |  | ||||||
| 	notpossible; | 	notpossible; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ PKGS += TOOL_BUILD | ||||||
| TOOL_BUILD_FILES := $(wildcard tool/build/*) | TOOL_BUILD_FILES := $(wildcard tool/build/*) | ||||||
| TOOL_BUILD_SRCS = $(filter %.c,$(TOOL_BUILD_FILES)) | TOOL_BUILD_SRCS = $(filter %.c,$(TOOL_BUILD_FILES)) | ||||||
| TOOL_BUILD_HDRS = $(filter %.h,$(TOOL_BUILD_FILES)) | TOOL_BUILD_HDRS = $(filter %.h,$(TOOL_BUILD_FILES)) | ||||||
| TOOL_BUILD_CTESTS = $(filter %.ctest,$(TOOL_BUILD_FILES)) |  | ||||||
| 
 | 
 | ||||||
| TOOL_BUILD_BINS =					\
 | TOOL_BUILD_BINS =					\
 | ||||||
| 	$(TOOL_BUILD_COMS)				\
 | 	$(TOOL_BUILD_COMS)				\
 | ||||||
|  | @ -21,8 +20,6 @@ TOOL_BUILD_BINS =					\ | ||||||
| 	o/$(MODE)/tool/build/printf			\
 | 	o/$(MODE)/tool/build/printf			\
 | ||||||
| 	o/$(MODE)/tool/build/dd | 	o/$(MODE)/tool/build/dd | ||||||
| 
 | 
 | ||||||
| TOOL_BUILD_CALCULATOR = o/$(MODE)/tool/build/calculator.com |  | ||||||
| 
 |  | ||||||
| TOOL_BUILD_OBJS =					\
 | TOOL_BUILD_OBJS =					\
 | ||||||
| 	$(TOOL_BUILD_SRCS:%.c=o/$(MODE)/%.o) | 	$(TOOL_BUILD_SRCS:%.c=o/$(MODE)/%.o) | ||||||
| 
 | 
 | ||||||
|  | @ -31,8 +28,7 @@ TOOL_BUILD_COMS =					\ | ||||||
| 
 | 
 | ||||||
| TOOL_BUILD_CHECKS =					\
 | TOOL_BUILD_CHECKS =					\
 | ||||||
| 	$(TOOL_BUILD).pkg				\
 | 	$(TOOL_BUILD).pkg				\
 | ||||||
| 	$(TOOL_BUILD_HDRS:%=o/$(MODE)/%.ok)		\
 | 	$(TOOL_BUILD_HDRS:%=o/$(MODE)/%.ok) | ||||||
| 	$(TOOL_BUILD_CTESTS:%=o/$(MODE)/%.ok) |  | ||||||
| 
 | 
 | ||||||
| TOOL_BUILD_DIRECTDEPS =					\
 | TOOL_BUILD_DIRECTDEPS =					\
 | ||||||
| 	DSP_CORE					\
 | 	DSP_CORE					\
 | ||||||
|  | @ -80,12 +76,6 @@ o/$(MODE)/tool/build/build.pkg:				\ | ||||||
| 		$(TOOL_BUILD_OBJS)			\
 | 		$(TOOL_BUILD_OBJS)			\
 | ||||||
| 		$(foreach x,$(TOOL_BUILD_DIRECTDEPS),$($(x)_A).pkg) | 		$(foreach x,$(TOOL_BUILD_DIRECTDEPS),$($(x)_A).pkg) | ||||||
| 
 | 
 | ||||||
| o/$(MODE)/%.ctest.ok:					\ |  | ||||||
| 		%.ctest					\
 |  | ||||||
| 		$(TOOL_BUILD_CALCULATOR)		\
 |  | ||||||
| 		$(VM) |  | ||||||
| 	@$(COMPILE) -AMKWIDES -wtT$@ $(VM) $(TOOL_BUILD_CALCULATOR) $< |  | ||||||
| 
 |  | ||||||
| o/$(MODE)/tool/build/%.com.dbg:				\ | o/$(MODE)/tool/build/%.com.dbg:				\ | ||||||
| 		$(TOOL_BUILD_DEPS)			\
 | 		$(TOOL_BUILD_DEPS)			\
 | ||||||
| 		o/$(MODE)/tool/build/build.pkg		\
 | 		o/$(MODE)/tool/build/build.pkg		\
 | ||||||
|  |  | ||||||
|  | @ -1,760 +0,0 @@ | ||||||
| #if 0 |  | ||||||
| /*─────────────────────────────────────────────────────────────────╗
 |  | ||||||
| │ To the extent possible under law, Justine Tunney has waived      │ |  | ||||||
| │ all copyright and related or neighboring rights to this file,    │ |  | ||||||
| │ as it is written in the following disclaimers:                   │ |  | ||||||
| │   • http://unlicense.org/                                        │
 |  | ||||||
| │   • http://creativecommons.org/publicdomain/zero/1.0/            │
 |  | ||||||
| ╚─────────────────────────────────────────────────────────────────*/ |  | ||||||
| #endif |  | ||||||
| #include "dsp/tty/tty.h" |  | ||||||
| #include "libc/assert.h" |  | ||||||
| #include "libc/calls/calls.h" |  | ||||||
| #include "libc/errno.h" |  | ||||||
| #include "libc/fmt/conv.h" |  | ||||||
| #include "libc/fmt/fmt.h" |  | ||||||
| #include "libc/fmt/itoa.h" |  | ||||||
| #include "libc/intrin/bits.h" |  | ||||||
| #include "libc/intrin/morton.h" |  | ||||||
| #include "libc/intrin/popcnt.h" |  | ||||||
| #include "libc/limits.h" |  | ||||||
| #include "libc/log/color.internal.h" |  | ||||||
| #include "libc/log/internal.h" |  | ||||||
| #include "libc/log/log.h" |  | ||||||
| #include "libc/macros.internal.h" |  | ||||||
| #include "libc/math.h" |  | ||||||
| #include "libc/mem/arraylist2.internal.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/rand.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/exit.h" |  | ||||||
| #include "libc/sysv/consts/sig.h" |  | ||||||
| #include "libc/tinymath/emodl.h" |  | ||||||
| #include "libc/x/xsigaction.h" |  | ||||||
| #include "third_party/gdtoa/gdtoa.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| 
 |  | ||||||
| #define INT     int128_t |  | ||||||
| #define FLOAT   long double |  | ||||||
| #define EPSILON 1e-16l |  | ||||||
| 
 |  | ||||||
| #define BANNER \ |  | ||||||
|   "\
 |  | ||||||
| Reverse Polish Notation Calculator\n\ |  | ||||||
| Copyright 2020 Justine Alexandra Roberts Tunney\n\ |  | ||||||
| This is fast portable lightweight software. You have the freedom to build\n\ |  | ||||||
| software just like it painlessly. See http://github.com/jart/cosmopolitan\n\ |  | ||||||
| " |  | ||||||
| 
 |  | ||||||
| #define USAGE1 \ |  | ||||||
|   "SYNOPSIS\n\
 |  | ||||||
| \n\ |  | ||||||
|   Reverse Polish Notation Calculator\n\ |  | ||||||
| \n\ |  | ||||||
| USAGE\n\ |  | ||||||
| \n" |  | ||||||
| 
 |  | ||||||
| #define USAGE2 \ |  | ||||||
|   " [FLAGS] [FILE...]\n\
 |  | ||||||
| \n\ |  | ||||||
| FLAGS\n\ |  | ||||||
| \n\ |  | ||||||
|   -h\n\ |  | ||||||
|   -?               shows this information\n\ |  | ||||||
|   -i               force interactive mode\n\ |  | ||||||
| \n\ |  | ||||||
| KEYBOARD SHORTCUTS\n\ |  | ||||||
| \n\ |  | ||||||
|   CTRL-D           Closes standard input\n\ |  | ||||||
|   CTRL-C           Sends SIGINT to program\n\ |  | ||||||
|   CTRL-U           Redraw line\n\ |  | ||||||
|   CTRL-L           Redraw display\n\ |  | ||||||
| \n\ |  | ||||||
| FUNCTIONS\n\ |  | ||||||
| \n" |  | ||||||
| 
 |  | ||||||
| #define USAGE3 \ |  | ||||||
|   "\n\
 |  | ||||||
| EXAMPLES\n\ |  | ||||||
| \n\ |  | ||||||
|   calculator.com\n\ |  | ||||||
|   40 2 +\n\ |  | ||||||
|   42\n\ |  | ||||||
| \n\ |  | ||||||
|   echo '2 2 + . cr' | calculator.com\n\ |  | ||||||
|   4\n\ |  | ||||||
| \n\ |  | ||||||
|   calculator.com <<EOF\n\ |  | ||||||
|   true assert\n\ |  | ||||||
|   -1 ~ 0 = assert\n\ |  | ||||||
|   3 2 / 1.5 = assert\n\ |  | ||||||
|   81 3 // 27 = assert\n\ |  | ||||||
|   2 8 ** 256 = assert\n\ |  | ||||||
|   pi cos -1 = assert\n\ |  | ||||||
|   pi sqrt pi sqrt * pi - abs epsilon < assert\n\ |  | ||||||
|   nan isnormal ! assert\n\ |  | ||||||
|   0b1010101 0b0110101 ^ 0b1100000 = assert\n\ |  | ||||||
|   0b1010101 popcnt 4 = assert\n\ |  | ||||||
|   EOF\n\ |  | ||||||
| \n\ |  | ||||||
| CONTACT\n\ |  | ||||||
| \n\ |  | ||||||
|   Justine Tunney <jtunney@gmail.com>\n\ |  | ||||||
|   https://github.com/jart/cosmooplitan\n\ |  | ||||||
| \n\ |  | ||||||
| " |  | ||||||
| 
 |  | ||||||
| #define CTRL(C)      ((C) ^ 0100) |  | ||||||
| #define Fatal(...)   Log(kFatal, __VA_ARGS__) |  | ||||||
| #define Warning(...) Log(kWarning, __VA_ARGS__) |  | ||||||
| 
 |  | ||||||
| enum Severity { |  | ||||||
|   kFatal, |  | ||||||
|   kWarning, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum Exception { |  | ||||||
|   kUnderflow = 1, |  | ||||||
|   kDivideError, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct Bytes { |  | ||||||
|   size_t i, n; |  | ||||||
|   char *p; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct History { |  | ||||||
|   size_t i, n; |  | ||||||
|   struct Bytes *p; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct Value { |  | ||||||
|   enum Type { |  | ||||||
|     kInt, |  | ||||||
|     kFloat, |  | ||||||
|   } t; |  | ||||||
|   union { |  | ||||||
|     INT i; |  | ||||||
|     FLOAT f; |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct Function { |  | ||||||
|   const char sym[16]; |  | ||||||
|   void (*fun)(void); |  | ||||||
|   const char *doc; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| jmp_buf thrower; |  | ||||||
| const char *file; |  | ||||||
| struct Bytes token; |  | ||||||
| struct History history; |  | ||||||
| struct Value stack[128]; |  | ||||||
| int sp, comment, line, column, interactive; |  | ||||||
| 
 |  | ||||||
| uint32_t gray(uint32_t x) { |  | ||||||
|   return x ^ (x >> 1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint32_t ungray(uint32_t x) { |  | ||||||
|   x ^= x >> 16; |  | ||||||
|   x ^= x >> 8; |  | ||||||
|   x ^= x >> 4; |  | ||||||
|   x ^= x >> 2; |  | ||||||
|   x ^= x >> 1; |  | ||||||
|   return x; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| INT Popcnt(INT x) { |  | ||||||
|   uint128_t word = x; |  | ||||||
|   return popcnt(word >> 64) + popcnt(word); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| char *Repr(struct Value x) { |  | ||||||
|   static char buf[64]; |  | ||||||
|   if (x.t == kFloat) { |  | ||||||
|     g_xfmt_p(buf, &x.f, 16, sizeof(buf), 0); |  | ||||||
|   } else { |  | ||||||
|     sprintf(buf, "%jjd", x.i); |  | ||||||
|   } |  | ||||||
|   return buf; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| char *ReprStack(void) { |  | ||||||
|   int i, j, l; |  | ||||||
|   char *s, *p; |  | ||||||
|   static char buf[80]; |  | ||||||
|   p = memset(buf, 0, sizeof(buf)); |  | ||||||
|   for (i = 0; i < sp; ++i) { |  | ||||||
|     s = Repr(stack[i]); |  | ||||||
|     l = strlen(s); |  | ||||||
|     if (p + l + 2 > buf + sizeof(buf)) break; |  | ||||||
|     p = mempcpy(p, s, l); |  | ||||||
|     *p++ = ' '; |  | ||||||
|   } |  | ||||||
|   return buf; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowStack(void) { |  | ||||||
|   if (interactive) { |  | ||||||
|     printf("\r\e[K"); |  | ||||||
|     fputs(ReprStack(), stdout); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Cr(FILE *f) { |  | ||||||
|   fputs(interactive || IsWindows() ? "\r\n" : "\n", f); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Log(enum Severity l, const char *fmt, ...) { |  | ||||||
|   va_list va; |  | ||||||
|   const char *severity[] = {"FATAL", "WARNING"}; |  | ||||||
|   if (interactive) fflush(/* key triggering throw not echo'd yet */ stdout); |  | ||||||
|   fprintf(stderr, "%s:%d:%d:%s: ", file, line + 1, column, severity[l & 1]); |  | ||||||
|   va_start(va, fmt); |  | ||||||
|   vfprintf(stderr, fmt, va); |  | ||||||
|   va_end(va); |  | ||||||
|   Cr(stderr); |  | ||||||
|   if (l == kFatal) exit(EXIT_FAILURE); |  | ||||||
|   if (interactive) ShowStack(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void __on_arithmetic_overflow(void) { |  | ||||||
|   Warning("arithmetic overflow"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OnDivideError(void) { |  | ||||||
|   longjmp(thrower, kDivideError); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct Value Push(struct Value x) { |  | ||||||
|   if (sp >= ARRAYLEN(stack)) Fatal("stack overflow"); |  | ||||||
|   return (stack[sp++] = x); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct Value Pop(void) { |  | ||||||
|   if (sp) { |  | ||||||
|     return stack[--sp]; |  | ||||||
|   } else { |  | ||||||
|     longjmp(thrower, kUnderflow); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| INT Popi(void) { |  | ||||||
|   struct Value x = Pop(); |  | ||||||
|   return x.t == kInt ? x.i : x.f; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Pushi(INT i) { |  | ||||||
|   struct Value x; |  | ||||||
|   x.t = kInt; |  | ||||||
|   x.i = i; |  | ||||||
|   Push(x); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| FLOAT Popf(void) { |  | ||||||
|   struct Value x = Pop(); |  | ||||||
|   return x.t == kInt ? x.i : x.f; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Pushf(FLOAT f) { |  | ||||||
|   struct Value x; |  | ||||||
|   x.t = kFloat; |  | ||||||
|   x.f = f; |  | ||||||
|   Push(x); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpDrop(void) { |  | ||||||
|   Pop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpDup(void) { |  | ||||||
|   Push(Push(Pop())); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpExit(void) { |  | ||||||
|   exit(Popi()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpSrand(void) { |  | ||||||
|   srand(Popi()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpEmit(void) { |  | ||||||
|   fputwc(Popi(), stdout); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpCr(void) { |  | ||||||
|   Cr(stdout); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpPrint(void) { |  | ||||||
|   printf("%s ", Repr(Pop())); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpComment(void) { |  | ||||||
|   comment = true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Glue0f(FLOAT fn(void)) { |  | ||||||
|   Pushf(fn()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Glue0i(INT fn(void)) { |  | ||||||
|   Pushi(fn()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Glue1f(FLOAT fn(FLOAT)) { |  | ||||||
|   Pushf(fn(Popf())); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Glue1i(INT fn(INT)) { |  | ||||||
|   Pushi(fn(Popi())); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpSwap(void) { |  | ||||||
|   struct Value a, b; |  | ||||||
|   b = Pop(); |  | ||||||
|   a = Pop(); |  | ||||||
|   Push(b); |  | ||||||
|   Push(a); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpOver(void) { |  | ||||||
|   struct Value a, b; |  | ||||||
|   b = Pop(); |  | ||||||
|   a = Pop(); |  | ||||||
|   Push(a); |  | ||||||
|   Push(b); |  | ||||||
|   Push(a); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpKey(void) { |  | ||||||
|   wint_t c; |  | ||||||
|   ttyraw(kTtyCursor | kTtySigs | kTtyLfToCrLf); |  | ||||||
|   c = fgetwc(stdin); |  | ||||||
|   ttyraw(-1); |  | ||||||
|   if (c != -1) Pushi(c); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpAssert(void) { |  | ||||||
|   if (!Popi()) Fatal("assert failed"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpExpect(void) { |  | ||||||
|   if (!Popi()) Warning("expect failed"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void OpMeminfo(void) { |  | ||||||
|   OpCr(); |  | ||||||
|   OpCr(); |  | ||||||
|   fflush(stdout); |  | ||||||
|   _meminfo(fileno(stdout)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Glue2f(FLOAT fn(FLOAT, FLOAT)) { |  | ||||||
|   FLOAT x, y; |  | ||||||
|   y = Popf(); |  | ||||||
|   x = Popf(); |  | ||||||
|   Pushf(fn(x, y)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Glue2i(INT fn(INT, INT)) { |  | ||||||
|   INT x, y; |  | ||||||
|   y = Popi(); |  | ||||||
|   x = Popi(); |  | ||||||
|   Pushi(fn(x, y)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Glue1g(FLOAT fnf(FLOAT), INT fni(INT)) { |  | ||||||
|   struct Value x; |  | ||||||
|   x = Pop(); |  | ||||||
|   switch (x.t) { |  | ||||||
|     case kInt: |  | ||||||
|       Pushi(fni(x.i)); |  | ||||||
|       break; |  | ||||||
|     case kFloat: |  | ||||||
|       Pushf(fnf(x.f)); |  | ||||||
|       break; |  | ||||||
|     default: |  | ||||||
|       Warning("type mismatch"); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Glue2g(FLOAT fnf(FLOAT, FLOAT), INT fni(INT, INT)) { |  | ||||||
|   struct Value x, y; |  | ||||||
|   y = Pop(); |  | ||||||
|   x = Pop(); |  | ||||||
|   if (x.t == kInt && y.t == kInt) { |  | ||||||
|     Pushi(fni(x.i, y.i)); |  | ||||||
|   } else if (x.t == kFloat && y.t == kFloat) { |  | ||||||
|     Pushf(fnf(x.f, y.f)); |  | ||||||
|   } else if (x.t == kInt && y.t == kFloat) { |  | ||||||
|     Pushf(fnf(x.i, y.f)); |  | ||||||
|   } else if (x.t == kFloat && y.t == kInt) { |  | ||||||
|     Pushf(fnf(x.f, y.i)); |  | ||||||
|   } else { |  | ||||||
|     Warning("type mismatch"); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #define LB                  { |  | ||||||
| #define RB                  } |  | ||||||
| #define SEMI                ; |  | ||||||
| #define FNTYPEi             INT |  | ||||||
| #define FNTYPEf             FLOAT |  | ||||||
| #define FORM(F)             LB F SEMI RB |  | ||||||
| #define FNPL0(T)            void |  | ||||||
| #define FNPL1(T)            FNTYPE##T x |  | ||||||
| #define FNPL2(T)            FNTYPE##T x, FNTYPE##T y |  | ||||||
| #define FNDEF(A, T, S, C)   FNTYPE##T Fn##S##T(FNPL##A(T)) FORM(return C) |  | ||||||
| #define FNDEFf(A, S, C)     FNDEF(A, f, S, C) |  | ||||||
| #define FNDEFi(A, S, C)     FNDEF(A, i, S, C) |  | ||||||
| #define FNDEFg(A, S, C)     FNDEF(A, f, S, C) FNDEF(A, i, S, C) |  | ||||||
| #define OPDEF(A, T, S, C)   void Op##S(void) FORM(Glue##A##T(Fn##S##T)) |  | ||||||
| #define OPDEFf(A, S, C)     OPDEF(A, f, S, C) |  | ||||||
| #define OPDEFi(A, S, C)     OPDEF(A, i, S, C) |  | ||||||
| #define OPDEFg(A, S, C)     void Op##S(void) FORM(Glue##A##g(Fn##S##f, Fn##S##i)) |  | ||||||
| #define M(A, T, N, S, C, D) FNDEF##T(A, S, C) OPDEF##T(A, S, C) |  | ||||||
| #include "tool/build/calculator.inc" |  | ||||||
| #undef M |  | ||||||
| 
 |  | ||||||
| const struct Function kFunctions[] = { |  | ||||||
|     {".", OpPrint, "pops prints value repr"}, |  | ||||||
|     {"#", OpComment, "line comment"}, |  | ||||||
| #define M(A, T, N, S, C, D) {N, Op##S, D}, |  | ||||||
| #include "tool/build/calculator.inc" |  | ||||||
| #undef M |  | ||||||
|     {"dup", OpDup, "pushes copy of last item on stack"}, |  | ||||||
|     {"drop", OpDrop, "pops and discards"}, |  | ||||||
|     {"swap", OpSwap, "swaps last two items on stack"}, |  | ||||||
|     {"over", OpOver, "pushes second item on stack"}, |  | ||||||
|     {"cr", OpCr, "prints newline"}, |  | ||||||
|     {"key", OpKey, "reads and pushes unicode character from keyboard"}, |  | ||||||
|     {"emit", OpEmit, "pops and writes unicode character to output"}, |  | ||||||
|     {"assert", OpAssert, "crashes if top of stack isn't nonzero"}, |  | ||||||
|     {"expect", OpExpect, "prints warning if top of stack isn't nonzero"}, |  | ||||||
|     {"meminfo", OpMeminfo, "prints memory mappings"}, |  | ||||||
|     {"exit", OpExit, "exits program with status"}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| bool CallFunction(const char *sym) { |  | ||||||
|   int i; |  | ||||||
|   char s[16]; |  | ||||||
|   strncpy(s, sym, sizeof(s)); |  | ||||||
|   for (i = 0; i < ARRAYLEN(kFunctions); ++i) { |  | ||||||
|     if (memcmp(kFunctions[i].sym, s, sizeof(s)) == 0) { |  | ||||||
|       kFunctions[i].fun(); |  | ||||||
|       return true; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| volatile const char *literal_; |  | ||||||
| bool ConsumeLiteral(const char *literal) { |  | ||||||
|   bool r; |  | ||||||
|   char *e; |  | ||||||
|   struct Value x; |  | ||||||
|   literal_ = literal; |  | ||||||
|   errno = 0; |  | ||||||
|   x.t = kInt; |  | ||||||
|   x.i = strtoi128(literal, &e, 0); |  | ||||||
|   if (*e) { |  | ||||||
|     x.t = kFloat; |  | ||||||
|     x.f = strtod(literal, &e); |  | ||||||
|     r = !(!e || *e); |  | ||||||
|   } else if (errno == ERANGE) { |  | ||||||
|     r = false; |  | ||||||
|   } else { |  | ||||||
|     r = true; |  | ||||||
|   } |  | ||||||
|   Push(x); |  | ||||||
|   return r; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ConsumeToken(void) { |  | ||||||
|   enum Exception ex; |  | ||||||
|   if (!token.i) return; |  | ||||||
|   token.p[token.i] = 0; |  | ||||||
|   token.i = 0; |  | ||||||
|   if (history.i) history.p[history.i - 1].i = 0; |  | ||||||
|   if (comment) return; |  | ||||||
|   if (_startswith(token.p, "#!")) return; |  | ||||||
|   switch (setjmp(thrower)) { |  | ||||||
|     default: |  | ||||||
|       if (CallFunction(token.p)) return; |  | ||||||
|       if (ConsumeLiteral(token.p)) return; |  | ||||||
|       Warning("bad token: %`'s", token.p); |  | ||||||
|       break; |  | ||||||
|     case kUnderflow: |  | ||||||
|       Warning("stack underflow"); |  | ||||||
|       break; |  | ||||||
|     case kDivideError: |  | ||||||
|       Warning("divide error"); |  | ||||||
|       break; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void CleanupRepl(void) { |  | ||||||
|   if (sp && interactive) { |  | ||||||
|     Cr(stdout); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void AppendByte(struct Bytes *a, char b) { |  | ||||||
|   APPEND(&a->p, &a->i, &a->n, &b); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void AppendHistory(void) { |  | ||||||
|   struct Bytes line; |  | ||||||
|   if (interactive) { |  | ||||||
|     bzero(&line, sizeof(line)); |  | ||||||
|     APPEND(&history.p, &history.i, &history.n, &line); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void AppendLine(char b) { |  | ||||||
|   if (interactive) { |  | ||||||
|     if (!history.i) AppendHistory(); |  | ||||||
|     AppendByte(&history.p[history.i - 1], b); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Echo(int c) { |  | ||||||
|   if (interactive) { |  | ||||||
|     fputc(c, stdout); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Backspace(int c) { |  | ||||||
|   struct Bytes *line; |  | ||||||
|   if (interactive) { |  | ||||||
|     if (history.i) { |  | ||||||
|       line = &history.p[history.i - 1]; |  | ||||||
|       if (line->i && token.i) { |  | ||||||
|         do { |  | ||||||
|           line->i--; |  | ||||||
|           token.i--; |  | ||||||
|         } while (line->i && token.i && (line->p[line->i] & 0x80)); |  | ||||||
|         fputs("\e[D \e[D", stdout); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void NewLine(void) { |  | ||||||
|   line++; |  | ||||||
|   column = 0; |  | ||||||
|   comment = false; |  | ||||||
|   if (interactive) { |  | ||||||
|     Cr(stdout); |  | ||||||
|     AppendHistory(); |  | ||||||
|     ShowStack(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KillLine(void) { |  | ||||||
|   if (interactive) { |  | ||||||
|     if (history.i) { |  | ||||||
|       history.p[history.i - 1].i--; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ClearLine(void) { |  | ||||||
|   if (interactive) { |  | ||||||
|     if (token.i) sp = 0; |  | ||||||
|     ShowStack(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void RedrawDisplay(void) { |  | ||||||
|   int i; |  | ||||||
|   struct Bytes *line; |  | ||||||
|   if (interactive) { |  | ||||||
|     printf("\e[H\e[2J%s", BANNER); |  | ||||||
|     ShowStack(); |  | ||||||
|     if (history.i) { |  | ||||||
|       line = &history.p[history.i - 1]; |  | ||||||
|       for (i = 0; i < line->i; ++i) { |  | ||||||
|         fputc(line->p[i], stdout); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GotoStartOfLine(void) { |  | ||||||
|   if (interactive) { |  | ||||||
|     printf("\r"); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GotoEndOfLine(void) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GotoPrevLine(void) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GotoNextLine(void) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GotoPrevChar(void) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GotoNextChar(void) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Calculator(FILE *f) { |  | ||||||
|   int c; |  | ||||||
|   while (!feof(f)) { |  | ||||||
|     switch ((c = getc(f))) { |  | ||||||
|       case -1: |  | ||||||
|       case CTRL('D'): |  | ||||||
|         goto Done; |  | ||||||
|       case CTRL('@'): |  | ||||||
|         break; |  | ||||||
|       case ' ': |  | ||||||
|         column++; |  | ||||||
|         Echo(c); |  | ||||||
|         AppendLine(c); |  | ||||||
|         ConsumeToken(); |  | ||||||
|         break; |  | ||||||
|       case '\t': |  | ||||||
|         column = ROUNDUP(column, 8); |  | ||||||
|         Echo(c); |  | ||||||
|         AppendLine(c); |  | ||||||
|         ConsumeToken(); |  | ||||||
|         break; |  | ||||||
|       case '\r': |  | ||||||
|       case '\n': |  | ||||||
|         ConsumeToken(); |  | ||||||
|         NewLine(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('A'): |  | ||||||
|         GotoStartOfLine(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('E'): |  | ||||||
|         GotoEndOfLine(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('P'): |  | ||||||
|         GotoPrevLine(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('N'): |  | ||||||
|         GotoNextLine(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('B'): |  | ||||||
|         GotoPrevChar(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('F'): |  | ||||||
|         GotoNextChar(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('L'): |  | ||||||
|         RedrawDisplay(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('U'): |  | ||||||
|         ClearLine(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('K'): |  | ||||||
|         KillLine(); |  | ||||||
|         break; |  | ||||||
|       case CTRL('?'): |  | ||||||
|       case CTRL('H'): |  | ||||||
|         Backspace(c); |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         column++; |  | ||||||
|         /* fallthrough */ |  | ||||||
|       case 0x80 ... 0xff: |  | ||||||
|         Echo(c); |  | ||||||
|         AppendLine(c); |  | ||||||
|         AppendByte(&token, c); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     fflush(/* needed b/c this is event loop */ stdout); |  | ||||||
|   } |  | ||||||
| Done: |  | ||||||
|   CleanupRepl(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int Calculate(const char *path) { |  | ||||||
|   FILE *f; |  | ||||||
|   file = path; |  | ||||||
|   line = column = 0; |  | ||||||
|   if (!(f = fopen(file, "r"))) Fatal("file not found: %s", file); |  | ||||||
|   Calculator(f); |  | ||||||
|   return fclose(f); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void CleanupTerminal(void) { |  | ||||||
|   ttyraw(-1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void StartInteractive(void) { |  | ||||||
|   if (!interactive && !__nocolor && isatty(fileno(stdin)) && |  | ||||||
|       isatty(fileno(stdout)) && !__nocolor) { |  | ||||||
|     interactive = true; |  | ||||||
|   } |  | ||||||
|   errno = 0; |  | ||||||
|   if (interactive) { |  | ||||||
|     fputs(BANNER, stdout); |  | ||||||
|     fflush(/* needed b/c entering tty mode */ stdout); |  | ||||||
|     ttyraw(kTtyCursor | kTtySigs); |  | ||||||
|     atexit(CleanupTerminal); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void PrintUsage(int rc, FILE *f) { |  | ||||||
|   char c; |  | ||||||
|   int i, j; |  | ||||||
|   fprintf(f, "%s  %s%s", USAGE1, program_invocation_name, USAGE2); |  | ||||||
|   for (i = 0; i < ARRAYLEN(kFunctions); ++i) { |  | ||||||
|     fputs("  ", f); |  | ||||||
|     for (j = 0; j < ARRAYLEN(kFunctions[i].sym); ++j) { |  | ||||||
|       c = kFunctions[i].sym[j]; |  | ||||||
|       fputc(c ? c : ' ', f); |  | ||||||
|     } |  | ||||||
|     fprintf(f, " %s\n", kFunctions[i].doc); |  | ||||||
|   } |  | ||||||
|   fputs(USAGE3, f); |  | ||||||
|   exit(rc); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GetOpts(int argc, char *argv[]) { |  | ||||||
|   int opt; |  | ||||||
|   while ((opt = getopt(argc, argv, "?hi")) != -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case 'i': |  | ||||||
|         interactive = true; |  | ||||||
|         break; |  | ||||||
|       case 'h': |  | ||||||
|       case '?': |  | ||||||
|         PrintUsage(EXIT_SUCCESS, stdout); |  | ||||||
|       default: |  | ||||||
|         PrintUsage(EX_USAGE, stderr); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int i, rc; |  | ||||||
|   ShowCrashReports(); |  | ||||||
|   GetOpts(argc, argv); |  | ||||||
|   xsigaction(SIGFPE, OnDivideError, 0, 0, 0); |  | ||||||
|   if (optind == argc) { |  | ||||||
|     file = "/dev/stdin"; |  | ||||||
|     StartInteractive(); |  | ||||||
|     Calculator(stdin); |  | ||||||
|     return fclose(stdin); |  | ||||||
|   } else { |  | ||||||
|     for (i = optind; i < argc; ++i) { |  | ||||||
|       if (Calculate(argv[i]) == -1) { |  | ||||||
|         return -1; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,91 +0,0 @@ | ||||||
| # INTEGER |  | ||||||
| 2 3 + 5 = assert |  | ||||||
| 3 2 + 5 = assert |  | ||||||
| 5 2 - 3 = assert |  | ||||||
| 2 5 - -3 = assert |  | ||||||
| 81 3 / 27 = assert |  | ||||||
| 81 3 // 27 = assert |  | ||||||
| 2 8 ** 256 = assert |  | ||||||
| 17 10 % 7 = assert |  | ||||||
| 17 10 fmod 7 = assert |  | ||||||
| 
 |  | ||||||
| # FLOATING POINT |  | ||||||
| .1 .2 + .3 - abs epsilon < assert |  | ||||||
| pi sqrt pi sqrt * pi - abs epsilon < assert |  | ||||||
| 3 2 / 1.5 = assert |  | ||||||
| pi pi = assert |  | ||||||
| pi cos -1 = assert |  | ||||||
| pi 2 / sin 1 = assert |  | ||||||
| 81 3 / 27 = assert |  | ||||||
| inf isinf assert |  | ||||||
| inf isnormal ! assert |  | ||||||
| nan isnormal ! assert |  | ||||||
| 1 0 / isnormal ! assert |  | ||||||
| 0 signbit ! assert |  | ||||||
| -.5 round -1 = assert |  | ||||||
| -.5 floor -1 = assert |  | ||||||
| -.5 rint dup 0 = assert signbit assert |  | ||||||
| -.5 nearbyint dup 0 = assert signbit assert |  | ||||||
| -.5 ceil dup 0 = assert signbit assert |  | ||||||
| -.5 trunc dup 0 = assert signbit assert |  | ||||||
| 0 0 / dup isnan assert signbit assert   # is this right? |  | ||||||
| 1 0 / dup isinf assert signbit ! assert # is this right? |  | ||||||
|  nan  nan != assert                     # is this right? |  | ||||||
| # -nan -nan != assert                   # is this right? |  | ||||||
|  inf  inf  = assert                     # is this right? |  | ||||||
| -inf -inf  = assert                     # is this right? |  | ||||||
| 
 |  | ||||||
| # BIT ARITHMETIC |  | ||||||
| -1 ~ 0 = assert |  | ||||||
| 0 0x7fffffffffffffffffffffffffffffff - -0x7fffffffffffffffffffffffffffffff = assert |  | ||||||
| 0b1010101 popcnt 4 = assert |  | ||||||
| 0b1010101 0b0110101 ^ 0b1100000 = assert |  | ||||||
| 0b1010101 0b0110101 | 0b1110101 = assert |  | ||||||
| 0b1010101 0b0110101 & 0b0010101 = assert |  | ||||||
| 0b1010101 1 >> 0b000101010 = assert |  | ||||||
| 0b1010101 2 >> 0b000010101 = assert |  | ||||||
| 0b1010101 1 << 0b010101010 = assert |  | ||||||
| 0b1010101 2 << 0b101010100 = assert |  | ||||||
| 
 |  | ||||||
| # BOOLEAN |  | ||||||
| true assert |  | ||||||
| false ! assert |  | ||||||
| true ! ! assert |  | ||||||
| true true && assert |  | ||||||
| true false && ! assert |  | ||||||
| false true && ! assert |  | ||||||
| true false && ! assert |  | ||||||
| false true && ! assert |  | ||||||
| true true || assert |  | ||||||
| false true || assert |  | ||||||
| true false || assert |  | ||||||
| false false || ! assert |  | ||||||
| 4 5 < assert |  | ||||||
| 5 4 < ! assert |  | ||||||
| -5 4 < assert |  | ||||||
| 5 5 < ! assert |  | ||||||
| 5 5 <= assert |  | ||||||
| 5 4 > assert |  | ||||||
| 4 5 > ! assert |  | ||||||
| 4 -5 > assert |  | ||||||
| 5 5 > ! assert |  | ||||||
| 5 5 >= assert |  | ||||||
| 
 |  | ||||||
| # MISC |  | ||||||
| 1 abs 1 = assert |  | ||||||
| -1 abs 1 = assert |  | ||||||
| -1 1 max 1 = assert |  | ||||||
| 1 -1 max 1 = assert |  | ||||||
| 1 2 max 2 = assert |  | ||||||
| -1 1 min -1 = assert |  | ||||||
| 1 -1 min -1 = assert |  | ||||||
| 1 2 min 1 = assert |  | ||||||
| rand64 rand64 rand64 rand64 != != && assert |  | ||||||
| 
 |  | ||||||
| # HEX SIGN |  | ||||||
|  -0x80000000 -2147483648 = assert |  | ||||||
|   0x80000000  2147483648 = assert |  | ||||||
|   0x80000001  2147483649 = assert |  | ||||||
|   0xffffffff  4294967295 = assert |  | ||||||
|  0x100000000  4294967296 = assert |  | ||||||
| -0x100000000 -4294967296 = assert |  | ||||||
|  | @ -1,100 +0,0 @@ | ||||||
| M(2, g, "+", Add, x + y, "add") |  | ||||||
| M(2, g, "-", Sub, x - y, "sub") |  | ||||||
| M(2, g, "*", Mul, x *y, "multiply") |  | ||||||
| M(2, f, "/", Div, x / y, "division") |  | ||||||
| M(2, i, "%", Rem, x % y, "integer remainder") |  | ||||||
| M(2, i, "//", Idiv, x / y, "integer division") |  | ||||||
| M(2, g, "**", Expo, powl(x, y), "exponentiation") |  | ||||||
| 
 |  | ||||||
| M(1, i, "~", Not, ~x, "bitwise not") |  | ||||||
| M(2, i, "^", Xor, x ^ y, "bitwise xor") |  | ||||||
| M(2, i, "|", Or, x | y, "bitwise or") |  | ||||||
| M(2, i, "&", And, x &y, "bitwise and") |  | ||||||
| M(2, i, ">>", Shr, x >> y, "shift right") |  | ||||||
| M(2, i, "<<", Shl, x << y, "shift left") |  | ||||||
| 
 |  | ||||||
| M(1, i, "!", LogicalNot, !x, "logical not") |  | ||||||
| M(2, i, "||", LogicalOr, x || y, "logical or") |  | ||||||
| M(2, i, "&&", LogicalAnd, x &&y, "logical and") |  | ||||||
| 
 |  | ||||||
| M(2, g, "=", Equal1, x == y, "equal to") |  | ||||||
| M(2, g, "!=", Notequal, x != y, "not equal to") |  | ||||||
| M(2, g, "<", LessThan, x < y, "less than") |  | ||||||
| M(2, g, ">", GreaterThan, x > y, "greater than") |  | ||||||
| M(2, g, "<=", LessThanEqual, x <= y, "less than or equal to") |  | ||||||
| M(2, g, ">=", GreaterThanEqual, x >= y, "greater than or equal to") |  | ||||||
| 
 |  | ||||||
| M(1, i, "gray", Gray, gray(x), "gray coding") |  | ||||||
| M(1, i, "ungray", Ungray, ungray(x), "inverse gray coding") |  | ||||||
| M(1, i, "popcnt", Popcnt, Popcnt(x), "count bits") |  | ||||||
| 
 |  | ||||||
| M(1, g, "abs", Abs, fabsl(x), "absolute value") |  | ||||||
| M(2, g, "min", Min, fminl(x, y), "pops two values and pushes minimum") |  | ||||||
| M(2, g, "max", Max, fmaxl(x, y), "pops two values and pushes maximum") |  | ||||||
| 
 |  | ||||||
| M(2, g, "fmod", Fmod, fmodl(x, y), "trunc remainder") |  | ||||||
| M(2, g, "emod", Emod, emodl(x, y), "euclidean remainder") |  | ||||||
| M(2, g, "remainder", Remainder, remainderl(x, y), "rint remainder") |  | ||||||
| M(2, g, "hypot", Hypot, hypotl(x, y), "euclidean distance") |  | ||||||
| 
 |  | ||||||
| M(0, i, "false", False, 0, "0") |  | ||||||
| M(0, i, "true", True, 1, "1") |  | ||||||
| M(0, i, "intmin", IntMin, INT128_MIN, "native integer minimum") |  | ||||||
| M(0, i, "intmax", IntMax, INT128_MAX, "native integer maximum") |  | ||||||
| M(0, f, "e", Euler, M_E, "𝑒") |  | ||||||
| M(0, f, "pi", Fldpi, M_PI, "π") |  | ||||||
| M(0, f, "epsilon", Epsilon, EPSILON, "ɛ") |  | ||||||
| M(0, f, "inf", Inf, INFINITY, "∞") |  | ||||||
| M(0, f, "nan", Nan, NAN, "NAN") |  | ||||||
| M(0, f, "-0", Negzero, -0., "wut") |  | ||||||
| M(0, f, "l2t", Fldl2t, M_LOG2_10, "log₂10") |  | ||||||
| M(0, f, "lg2", Fldlg2, M_LOG10_2, "log₁₀2") |  | ||||||
| M(0, f, "ln2", Fldln2, M_LN2, "logₑ2") |  | ||||||
| M(0, f, "l2e", Fldl2e, M_LOG2E, "logₑ10") |  | ||||||
| M(2, f, "nextafter", Nextafter, nextafterl(x, y), "next ulp") |  | ||||||
| M(1, f, "significand", Significand, significandl(x), "mantissa") |  | ||||||
| 
 |  | ||||||
| M(1, f, "sqrt", Sqrt, sqrtl(x), "√𝑥") |  | ||||||
| M(1, f, "exp", Exp, expl(x), "𝑒ˣ") |  | ||||||
| M(1, g, "expm1", Expm1, expm1l(x), "𝑒ˣ-1") |  | ||||||
| M(1, g, "exp2", Exp2, exp2l(x), "2ˣ") |  | ||||||
| M(1, g, "exp10", Exp10, exp10l(x), "10ˣ") |  | ||||||
| M(2, g, "ldexp", Ldexp, ldexpl(x, y), "𝑥×2ʸ") |  | ||||||
| 
 |  | ||||||
| M(1, f, "log", Log, logl(x), "logₑ𝑥") |  | ||||||
| M(1, g, "log2", Log2, log2l(x), "log₂𝑥") |  | ||||||
| M(1, g, "log10", Log10, log10l(x), "log₁₀𝑥") |  | ||||||
| M(1, g, "ilogb", Ilogb, ilogbl(x), "exponent") |  | ||||||
| 
 |  | ||||||
| M(1, g, "sin", Sin, sinl(x), "sine") |  | ||||||
| M(1, g, "cos", Cos, cosl(x), "cosine") |  | ||||||
| M(1, g, "tan", Tan, tanl(x), "tangent") |  | ||||||
| M(1, g, "asin", Asin, asinl(x), "arcsine") |  | ||||||
| M(1, g, "acos", Acos, acosl(x), "arccosine") |  | ||||||
| M(1, g, "atan", Atan, atanl(x), "arctangent") |  | ||||||
| M(2, g, "atan2", Atan2, atan2l(x, y), "arctangent of 𝑥/𝑦") |  | ||||||
| 
 |  | ||||||
| M(1, g, "sinh", Sinh, sinhl(x), "hyperbolic sine") |  | ||||||
| M(1, g, "cosh", Cosh, coshl(x), "hyperbolic cosine") |  | ||||||
| M(1, g, "tanh", Tanh, tanhl(x), "hyperbolic tangent") |  | ||||||
| M(1, g, "asinh", Asinh, asinhl(x), "hyperbolic arcsine") |  | ||||||
| M(1, g, "acosh", Acosh, acoshl(x), "hyperbolic arccosine") |  | ||||||
| M(1, g, "atanh", Atanh, atanhl(x), "hyperbolic arctangent") |  | ||||||
| 
 |  | ||||||
| M(1, g, "round", Round, roundl(x), "round away from zero") |  | ||||||
| M(1, g, "trunc", Trunc, truncl(x), "round towards zero") |  | ||||||
| M(1, g, "rint", Rint, rintl(x), "round to even") |  | ||||||
| M(1, g, "nearbyint", Nearbyint, nearbyintl(x), "round to nearest integer") |  | ||||||
| M(1, g, "ceil", Ceil, ceill(x), "smallest integral not less than 𝑥") |  | ||||||
| M(1, g, "floor", Floor, floorl(x), "largest integral not greater than 𝑥") |  | ||||||
| 
 |  | ||||||
| M(1, f, "isnan", Isnan, isnan(x), "returns true if 𝑥=NAN") |  | ||||||
| M(1, f, "isinf", Isinf, isinf(x), "returns true if 𝑥=INFINITY") |  | ||||||
| M(1, f, "signbit", Signbit, signbit(x), "clears all bits but sign bit") |  | ||||||
| M(1, f, "isfinite", Isfinite, isfinite(x), "returns true if 𝑥≠INFINITY") |  | ||||||
| M(1, f, "isnormal", Isnormal, isnormal(x), "returns true if not denormal") |  | ||||||
| M(1, f, "fpclassify", Fpclassify, fpclassify(x), |  | ||||||
|   "nan=0,inf=1,zero=2,subnorm=3,normal=4") |  | ||||||
| 
 |  | ||||||
| M(0, i, "rand", Rand, rand(), "deterministic random number") |  | ||||||
| M(0, i, "rand64", _Rand64, _rand64(), "64-bit random number") |  | ||||||
|  | @ -21,6 +21,7 @@ | ||||||
| #include "libc/fmt/conv.h" | #include "libc/fmt/conv.h" | ||||||
| #include "libc/fmt/magnumstrs.internal.h" | #include "libc/fmt/magnumstrs.internal.h" | ||||||
| #include "libc/runtime/runtime.h" | #include "libc/runtime/runtime.h" | ||||||
|  | #include "libc/stdio/stdio.h" | ||||||
| #include "libc/str/str.h" | #include "libc/str/str.h" | ||||||
| #include "third_party/getopt/getopt.internal.h" | #include "third_party/getopt/getopt.internal.h" | ||||||
| 
 | 
 | ||||||
|  | @ -33,42 +34,21 @@ SYNOPSIS\n\ | ||||||
| \n\ | \n\ | ||||||
| FLAGS\n\ | FLAGS\n\ | ||||||
| \n\ | \n\ | ||||||
|   -?\n\ |  | ||||||
|   -h      help\n\ |   -h      help\n\ | ||||||
| \n" | \n" | ||||||
| 
 | 
 | ||||||
| const char *prog; | const char *prog; | ||||||
| 
 | 
 | ||||||
| nullterminated() static void Print(int fd, const char *s, ...) { |  | ||||||
|   va_list va; |  | ||||||
|   char buf[2048]; |  | ||||||
|   va_start(va, s); |  | ||||||
|   buf[0] = 0; |  | ||||||
|   do { |  | ||||||
|     strlcat(buf, s, sizeof(buf)); |  | ||||||
|   } while ((s = va_arg(va, const char *))); |  | ||||||
|   write(fd, buf, strlen(buf)); |  | ||||||
|   va_end(va); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static wontreturn void SysExit(const char *path, const char *func) { |  | ||||||
|   const char *errstr; |  | ||||||
|   if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN"; |  | ||||||
|   Print(2, path, ": ", func, " failed with ", errstr, "\n", NULL); |  | ||||||
|   exit(1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static wontreturn void PrintUsage(int fd, int rc) { | static wontreturn void PrintUsage(int fd, int rc) { | ||||||
|   Print(fd, "USAGE\n\n  ", program_invocation_name, USAGE, NULL); |   tinyprint(fd, "USAGE\n\n  ", prog, USAGE, NULL); | ||||||
|   exit(rc); |   exit(rc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void GetOpts(int argc, char *argv[]) { | static void GetOpts(int argc, char *argv[]) { | ||||||
|   int opt; |   int opt; | ||||||
|   while ((opt = getopt(argc, argv, "?h")) != -1) { |   while ((opt = getopt(argc, argv, "h")) != -1) { | ||||||
|     switch (opt) { |     switch (opt) { | ||||||
|       case 'h': |       case 'h': | ||||||
|       case '?': |  | ||||||
|         PrintUsage(1, 0); |         PrintUsage(1, 0); | ||||||
|       default: |       default: | ||||||
|         PrintUsage(2, 1); |         PrintUsage(2, 1); | ||||||
|  | @ -79,18 +59,22 @@ static void GetOpts(int argc, char *argv[]) { | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   int i, mode; |   int i, mode; | ||||||
|   char buf[PATH_MAX], *endptr; |   char buf[PATH_MAX], *endptr; | ||||||
|  |   prog = argv[0]; | ||||||
|  |   if (!prog) prog = "chmod"; | ||||||
|   GetOpts(argc, argv); |   GetOpts(argc, argv); | ||||||
|   if (argc - optind < 2) { |   if (argc - optind < 2) { | ||||||
|     PrintUsage(2, 1); |     tinyprint(2, prog, ": missing operand\n", NULL); | ||||||
|  |     exit(1); | ||||||
|   } |   } | ||||||
|   mode = strtol(argv[optind], &endptr, 8) & 07777; |   mode = strtol(argv[optind], &endptr, 8) & 07777; | ||||||
|   if (*endptr) { |   if (*endptr) { | ||||||
|     Print(2, "chmod: invalid mode octal\n", NULL); |     tinyprint(2, prog, ": invalid mode octal\n", NULL); | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
|   for (i = optind + 1; i < argc; ++i) { |   for (i = optind + 1; i < argc; ++i) { | ||||||
|     if (chmod(argv[i], mode) == -1) { |     if (chmod(argv[i], mode) == -1) { | ||||||
|       SysExit(argv[i], "chmod"); |       perror(argv[i]); | ||||||
|  |       exit(1); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return 0; |   return 0; | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ | ||||||
| #include "libc/fmt/fmt.h" | #include "libc/fmt/fmt.h" | ||||||
| #include "libc/fmt/libgen.h" | #include "libc/fmt/libgen.h" | ||||||
| #include "libc/fmt/magnumstrs.internal.h" | #include "libc/fmt/magnumstrs.internal.h" | ||||||
|  | #include "libc/intrin/kprintf.h" | ||||||
| #include "libc/mem/gc.h" | #include "libc/mem/gc.h" | ||||||
| #include "libc/runtime/runtime.h" | #include "libc/runtime/runtime.h" | ||||||
| #include "libc/stdio/stdio.h" | #include "libc/stdio/stdio.h" | ||||||
|  | @ -91,16 +92,14 @@ bool IsSymlink(const char *path) { | ||||||
|   return res; |   return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| wontreturn void PrintUsage(int rc, FILE *f) { | wontreturn void PrintUsage(int rc, int fd) { | ||||||
|   fputs("usage: ", f); |   tinyprint(fd, "USAGE\n\n  ", prog, USAGE, NULL); | ||||||
|   fputs(prog, f); |  | ||||||
|   fputs(USAGE, f); |  | ||||||
|   exit(rc); |   exit(rc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetOpts(int argc, char *argv[]) { | void GetOpts(int argc, char *argv[]) { | ||||||
|   int opt; |   int opt; | ||||||
|   while ((opt = getopt(argc, argv, "?hfnaprR")) != -1) { |   while ((opt = getopt(argc, argv, "hfnaprR")) != -1) { | ||||||
|     switch (opt) { |     switch (opt) { | ||||||
|       case 'f': |       case 'f': | ||||||
|         force = true; |         force = true; | ||||||
|  | @ -118,10 +117,9 @@ void GetOpts(int argc, char *argv[]) { | ||||||
|         flags |= COPYFILE_PRESERVE_TIMESTAMPS; |         flags |= COPYFILE_PRESERVE_TIMESTAMPS; | ||||||
|         break; |         break; | ||||||
|       case 'h': |       case 'h': | ||||||
|       case '?': |         PrintUsage(0, 1); | ||||||
|         PrintUsage(EXIT_SUCCESS, stdout); |  | ||||||
|       default: |       default: | ||||||
|         PrintUsage(EX_USAGE, stderr); |         PrintUsage(1, 2); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | @ -146,8 +144,7 @@ int Visit(const char *fpath, const struct stat *sb, int tflag, | ||||||
|       Cp(srcfile, dstfile); |       Cp(srcfile, dstfile); | ||||||
|       return 0; |       return 0; | ||||||
|     default: |     default: | ||||||
|       fputs(fpath, stderr); |       tinyprint(2, fpath, ": bad file type\n", NULL); | ||||||
|       fputs(": can't handle file type\n", stderr); |  | ||||||
|       exit(1); |       exit(1); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | @ -157,7 +154,7 @@ char *Join(const char *a, const char *b) { | ||||||
|   n = strlen(a); |   n = strlen(a); | ||||||
|   m = strlen(b); |   m = strlen(b); | ||||||
|   if (n + 1 + m + 1 > sizeof(dstfile)) { |   if (n + 1 + m + 1 > sizeof(dstfile)) { | ||||||
|     fputs("error: cp: path too long\n", stderr); |     tinyprint(2, prog, ": path too long\n", NULL); | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
|   stpcpy(stpcpy(stpcpy(dstfile, a), "/"), b); |   stpcpy(stpcpy(stpcpy(dstfile, a), "/"), b); | ||||||
|  | @ -191,8 +188,7 @@ void Cp(char *src, char *dst) { | ||||||
|   basename(dst); |   basename(dst); | ||||||
|   if (IsDirectory(src)) { |   if (IsDirectory(src)) { | ||||||
|     if (!recursive) { |     if (!recursive) { | ||||||
|       fputs(prog, stderr); |       tinyprint(2, prog, ": won't copy directory without -r flag\n", NULL); | ||||||
|       fputs(": won't copy directory without -r flag.\n", stderr); |  | ||||||
|       exit(1); |       exit(1); | ||||||
|     } |     } | ||||||
|     strcpy(dstdir, dst); |     strcpy(dstdir, dst); | ||||||
|  | @ -208,10 +204,7 @@ void Cp(char *src, char *dst) { | ||||||
|       strcpy(srcdir, ""); |       strcpy(srcdir, ""); | ||||||
|     } |     } | ||||||
|     if (nftw(src, Visit, 20, 0) == -1) { |     if (nftw(src, Visit, 20, 0) == -1) { | ||||||
|       fputs(prog, stderr); |       perror(src); | ||||||
|       fputs(": nftw failed: ", stderr); |  | ||||||
|       fputs(_strerdoc(errno), stderr); |  | ||||||
|       fputs("\n", stderr); |  | ||||||
|       exit(1); |       exit(1); | ||||||
|     } |     } | ||||||
|     return; |     return; | ||||||
|  | @ -219,37 +212,49 @@ void Cp(char *src, char *dst) { | ||||||
|   if (IsDirectory(dst)) { |   if (IsDirectory(dst)) { | ||||||
|     dst = Join(dst, basename(src)); |     dst = Join(dst, basename(src)); | ||||||
|   } |   } | ||||||
|   if (!force && access(dst, W_OK) == -1 && errno != ENOENT) goto OnFail; |   if (!force && access(dst, W_OK) == -1 && errno != ENOENT) { | ||||||
|   strcpy(mkbuf, dst); |     perror(dst); | ||||||
|   if (makedirs(dirname(mkbuf), 0755) == -1) goto OnFail; |     exit(1); | ||||||
|   if (IsSymlink(src)) { |   } | ||||||
|     if ((rc = readlink(src, linkbuf, sizeof(linkbuf) - 1)) == -1) goto OnFail; |   strcpy(mkbuf, dst); | ||||||
|     linkbuf[rc] = 0; |   if (makedirs((s = dirname(mkbuf)), 0755) == -1) { | ||||||
|     if (symlink(linkbuf, dst) == -1) goto OnFail; |     perror(s); | ||||||
|   } else { |     exit(1); | ||||||
|     if (!MovePreservingDestinationInode(src, dst)) goto OnFail; |   } | ||||||
|  |   if (IsSymlink(src)) { | ||||||
|  |     if ((rc = readlink(src, linkbuf, sizeof(linkbuf) - 1)) == -1) { | ||||||
|  |       perror(src); | ||||||
|  |       exit(1); | ||||||
|  |     } | ||||||
|  |     linkbuf[rc] = 0; | ||||||
|  |     if (symlink(linkbuf, dst) == -1) { | ||||||
|  |       perror(dst); | ||||||
|  |       exit(1); | ||||||
|  |     } | ||||||
|  |   } else { | ||||||
|  |     if (!MovePreservingDestinationInode(src, dst)) { | ||||||
|  |       perror(src); | ||||||
|  |       exit(1); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|   return; |  | ||||||
| OnFail: |  | ||||||
|   s = _strerdoc(errno); |  | ||||||
|   fputs(prog, stderr); |  | ||||||
|   fputs(": ", stderr); |  | ||||||
|   fputs(src, stderr); |  | ||||||
|   fputs(" ", stderr); |  | ||||||
|   fputs(dst, stderr); |  | ||||||
|   fputs(": ", stderr); |  | ||||||
|   fputs(s, stderr); |  | ||||||
|   fputs("\n", stderr); |  | ||||||
|   exit(1); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   int i; |   int i; | ||||||
|   prog = argc > 0 ? argv[0] : "cp.com"; | 
 | ||||||
|  |   prog = argv[0]; | ||||||
|  |   if (!prog) prog = "cp"; | ||||||
|  | 
 | ||||||
|   GetOpts(argc, argv); |   GetOpts(argc, argv); | ||||||
|   if (argc - optind < 2) PrintUsage(EX_USAGE, stderr); | 
 | ||||||
|  |   if (argc - optind < 2) { | ||||||
|  |     tinyprint(2, prog, ": missing operand\n", NULL); | ||||||
|  |     exit(1); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   for (i = optind; i < argc - 1; ++i) { |   for (i = optind; i < argc - 1; ++i) { | ||||||
|     Cp(argv[i], argv[argc - 1]); |     Cp(argv[i], argv[argc - 1]); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -73,32 +73,20 @@ static const char *epath; | ||||||
| static Elf64_Xword symcount; | static Elf64_Xword symcount; | ||||||
| static const Elf64_Ehdr *elf; | static const Elf64_Ehdr *elf; | ||||||
| 
 | 
 | ||||||
| nullterminated() static void Print(int fd, const char *s, ...) { |  | ||||||
|   va_list va; |  | ||||||
|   char buf[2048]; |  | ||||||
|   va_start(va, s); |  | ||||||
|   buf[0] = 0; |  | ||||||
|   do { |  | ||||||
|     strlcat(buf, s, sizeof(buf)); |  | ||||||
|   } while ((s = va_arg(va, const char *))); |  | ||||||
|   write(fd, buf, strlen(buf)); |  | ||||||
|   va_end(va); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static wontreturn void Die(const char *reason) { | static wontreturn void Die(const char *reason) { | ||||||
|   Print(2, epath, ": ", reason, "\n", NULL); |   tinyprint(2, epath, ": ", reason, "\n", NULL); | ||||||
|   exit(1); |   exit(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static wontreturn void SysExit(const char *func) { | static wontreturn void SysExit(const char *func) { | ||||||
|   const char *errstr; |   const char *errstr; | ||||||
|   if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN"; |   if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN"; | ||||||
|   Print(2, epath, ": ", func, " failed with ", errstr, "\n", NULL); |   tinyprint(2, epath, ": ", func, " failed with ", errstr, "\n", NULL); | ||||||
|   exit(1); |   exit(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static wontreturn void PrintUsage(int fd, int exitcode) { | static wontreturn void PrintUsage(int fd, int exitcode) { | ||||||
|   Print(fd, "\n\
 |   tinyprint(fd, "\n\
 | ||||||
| NAME\n\ | NAME\n\ | ||||||
| \n\ | \n\ | ||||||
|   Cosmopolitan Object Fixer\n\ |   Cosmopolitan Object Fixer\n\ | ||||||
|  | @ -106,7 +94,7 @@ NAME\n\ | ||||||
| SYNOPSIS\n\ | SYNOPSIS\n\ | ||||||
| \n\ | \n\ | ||||||
|   ", |   ", | ||||||
|         program_invocation_name, " [FLAGS] OBJECT...\n\
 |             program_invocation_name, " [FLAGS] OBJECT...\n\
 | ||||||
| \n\ | \n\ | ||||||
| DESCRIPTION\n\ | DESCRIPTION\n\ | ||||||
| \n\ | \n\ | ||||||
|  | @ -124,7 +112,7 @@ FLAGS\n\ | ||||||
|   -c            checks only mode\n\ |   -c            checks only mode\n\ | ||||||
| \n\ | \n\ | ||||||
| ", | ", | ||||||
|         NULL); |             NULL); | ||||||
|   exit(exitcode); |   exit(exitcode); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -143,10 +131,10 @@ static void GetOpts(int argc, char *argv[]) { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (optind == argc) { |   if (optind == argc) { | ||||||
|     Print(2, |     tinyprint(2, | ||||||
|           "error: no elf object files specified\n" |               "error: no elf object files specified\n" | ||||||
|           "run ", |               "run ", | ||||||
|           program_invocation_name, " -h for usage\n", NULL); |               program_invocation_name, " -h for usage\n", NULL); | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | @ -184,11 +172,11 @@ static void CheckPrivilegedCrossReferences(void) { | ||||||
|       if (~shdr->sh_flags & SHF_EXECINSTR) continue;  // data reference
 |       if (~shdr->sh_flags & SHF_EXECINSTR) continue;  // data reference
 | ||||||
|       if ((secname = GetElfString(elf, esize, secstrs, shdr->sh_name)) && |       if ((secname = GetElfString(elf, esize, secstrs, shdr->sh_name)) && | ||||||
|           strcmp(".privileged", secname)) { |           strcmp(".privileged", secname)) { | ||||||
|         Print(2, epath, |         tinyprint(2, epath, | ||||||
|               ": code in .privileged section " |                   ": code in .privileged section " | ||||||
|               "references symbol '", |                   "references symbol '", | ||||||
|               GetElfString(elf, esize, symstrs, syms[x].st_name), |                   GetElfString(elf, esize, symstrs, syms[x].st_name), | ||||||
|               "' in unprivileged code section '", secname, "'\n", NULL); |                   "' in unprivileged code section '", secname, "'\n", NULL); | ||||||
|         exit(1); |         exit(1); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -289,7 +289,8 @@ void Decompress(const char *inpath) { | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   int i; |   int i; | ||||||
|   prog = argc > 0 ? argv[0] : "cp.com"; |   prog = argv[0]; | ||||||
|  |   if (!prog) prog = "gzip"; | ||||||
|   GetOpts(argc, argv); |   GetOpts(argc, argv); | ||||||
|   if (opt_decompress) { |   if (opt_decompress) { | ||||||
|     if (optind == argc) { |     if (optind == argc) { | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ void PrintUsage(int rc, FILE *f) { | ||||||
| void GetOpts(int argc, char *argv[]) { | void GetOpts(int argc, char *argv[]) { | ||||||
|   int opt; |   int opt; | ||||||
|   bits_ = 64; |   bits_ = 64; | ||||||
|   while ((opt = getopt(argc, argv, "?hbs")) != -1) { |   while ((opt = getopt(argc, argv, "hbs")) != -1) { | ||||||
|     switch (opt) { |     switch (opt) { | ||||||
|       case 's': |       case 's': | ||||||
|         succinct_ = true; |         succinct_ = true; | ||||||
|  | @ -60,7 +60,6 @@ void GetOpts(int argc, char *argv[]) { | ||||||
|       case 'b': |       case 'b': | ||||||
|         bits_ = atoi(optarg); |         bits_ = atoi(optarg); | ||||||
|         break; |         break; | ||||||
|       case '?': |  | ||||||
|       case 'h': |       case 'h': | ||||||
|         PrintUsage(EXIT_SUCCESS, stdout); |         PrintUsage(EXIT_SUCCESS, stdout); | ||||||
|       default: |       default: | ||||||
|  |  | ||||||
|  | @ -8,14 +8,9 @@ | ||||||
| ╚─────────────────────────────────────────────────────────────────*/ | ╚─────────────────────────────────────────────────────────────────*/ | ||||||
| #endif | #endif | ||||||
| #include "libc/calls/calls.h" | #include "libc/calls/calls.h" | ||||||
| #include "libc/errno.h" |  | ||||||
| #include "libc/fmt/conv.h" | #include "libc/fmt/conv.h" | ||||||
| #include "libc/fmt/magnumstrs.internal.h" |  | ||||||
| #include "libc/runtime/runtime.h" | #include "libc/runtime/runtime.h" | ||||||
| #include "libc/stdio/stdio.h" | #include "libc/stdio/stdio.h" | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/x/x.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" | #include "third_party/getopt/getopt.internal.h" | ||||||
| 
 | 
 | ||||||
| #define USAGE \ | #define USAGE \ | ||||||
|  | @ -30,19 +25,19 @@ FLAGS\n\ | ||||||
| 
 | 
 | ||||||
| const char *prog; | const char *prog; | ||||||
| 
 | 
 | ||||||
| wontreturn void PrintUsage(int rc, FILE *f) { | wontreturn void PrintUsage(int rc, int fd) { | ||||||
|   fputs("Usage: ", f); |   tinyprint(fd, "USAGE\n\n  ", prog, USAGE, NULL); | ||||||
|   fputs(prog, f); |  | ||||||
|   fputs(USAGE, f); |  | ||||||
|   exit(rc); |   exit(rc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   int i, mode = 0755; |   int i, mode = 0755; | ||||||
|   int (*mkdirp)(const char *, unsigned) = mkdir; |   int (*mkdirp)(const char *, unsigned) = mkdir; | ||||||
|   prog = argc > 0 ? argv[0] : "mkdir.com"; |  | ||||||
| 
 | 
 | ||||||
|   while ((i = getopt(argc, argv, "?hpm:")) != -1) { |   prog = argv[0]; | ||||||
|  |   if (!prog) prog = "mkdir"; | ||||||
|  | 
 | ||||||
|  |   while ((i = getopt(argc, argv, "hpm:")) != -1) { | ||||||
|     switch (i) { |     switch (i) { | ||||||
|       case 'p': |       case 'p': | ||||||
|         mkdirp = makedirs; |         mkdirp = makedirs; | ||||||
|  | @ -50,31 +45,21 @@ int main(int argc, char *argv[]) { | ||||||
|       case 'm': |       case 'm': | ||||||
|         mode = strtol(optarg, 0, 8); |         mode = strtol(optarg, 0, 8); | ||||||
|         break; |         break; | ||||||
|       case '?': |  | ||||||
|       case 'h': |       case 'h': | ||||||
|         PrintUsage(0, stdout); |         PrintUsage(0, 1); | ||||||
|       default: |       default: | ||||||
|         PrintUsage(EX_USAGE, stderr); |         PrintUsage(1, 2); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (optind == argc) { |   if (optind == argc) { | ||||||
|     fputs(prog, stderr); |     tinyprint(2, prog, ": missing operand\n", NULL); | ||||||
|     fputs(": missing argument\n", stderr); |  | ||||||
|     fputs("Try '", stderr); |  | ||||||
|     fputs(prog, stderr); |  | ||||||
|     fputs(" -h' for more information.\n", stderr); |  | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   for (i = optind; i < argc; ++i) { |   for (i = optind; i < argc; ++i) { | ||||||
|     if (mkdirp(argv[i], mode) == -1) { |     if (mkdirp(argv[i], mode) == -1) { | ||||||
|       fputs(prog, stderr); |       perror(argv[i]); | ||||||
|       fputs(": cannot create directory '", stderr); |  | ||||||
|       fputs(argv[i], stderr); |  | ||||||
|       fputs("' ", stderr); |  | ||||||
|       fputs(_strerdoc(errno), stderr); |  | ||||||
|       fputc('\n', stderr); |  | ||||||
|       exit(1); |       exit(1); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -62,27 +62,15 @@ char linkbuf[PATH_MAX]; | ||||||
| 
 | 
 | ||||||
| void Mv(char *, char *); | void Mv(char *, char *); | ||||||
| 
 | 
 | ||||||
| nullterminated() void Print(int fd, const char *s, ...) { |  | ||||||
|   va_list va; |  | ||||||
|   char buf[2048]; |  | ||||||
|   va_start(va, s); |  | ||||||
|   buf[0] = 0; |  | ||||||
|   do { |  | ||||||
|     strlcat(buf, s, sizeof(buf)); |  | ||||||
|   } while ((s = va_arg(va, const char *))); |  | ||||||
|   write(fd, buf, strlen(buf)); |  | ||||||
|   va_end(va); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| wontreturn void Die(const char *path, const char *reason) { | wontreturn void Die(const char *path, const char *reason) { | ||||||
|   Print(2, path, ": ", reason, "\n", NULL); |   tinyprint(2, path, ": ", reason, "\n", NULL); | ||||||
|   exit(1); |   exit(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| wontreturn void SysExit(const char *path, const char *func) { | wontreturn void SysDie(const char *path, const char *func) { | ||||||
|   const char *errstr; |   const char *errstr; | ||||||
|   if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN"; |   if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN"; | ||||||
|   Print(2, path, ": ", func, "() failed with ", errstr, "\n", NULL); |   tinyprint(2, path, ": ", func, ": ", errstr, "\n", NULL); | ||||||
|   exit(1); |   exit(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -108,7 +96,7 @@ bool IsSymlink(const char *path) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| wontreturn void PrintUsage(int rc, int fd) { | wontreturn void PrintUsage(int rc, int fd) { | ||||||
|   Print(fd, "usage: ", prog, USAGE, NULL); |   tinyprint(fd, "usage: ", prog, USAGE, NULL); | ||||||
|   exit(rc); |   exit(rc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -161,7 +149,7 @@ char *Join(const char *a, const char *b) { | ||||||
|   n = strlen(a); |   n = strlen(a); | ||||||
|   m = strlen(b); |   m = strlen(b); | ||||||
|   if (n + 1 + m + 1 > sizeof(dstfile)) { |   if (n + 1 + m + 1 > sizeof(dstfile)) { | ||||||
|     Print(2, "error: mv: path too long\n", NULL); |     tinyprint(2, "error: mv: path too long\n", NULL); | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
|   stpcpy(stpcpy(stpcpy(dstfile, a), "/"), b); |   stpcpy(stpcpy(stpcpy(dstfile, a), "/"), b); | ||||||
|  | @ -192,7 +180,7 @@ void Mv(char *src, char *dst) { | ||||||
|       strcpy(srcdir, ""); |       strcpy(srcdir, ""); | ||||||
|     } |     } | ||||||
|     if (nftw(src, Visit, 20, 0) == -1) { |     if (nftw(src, Visit, 20, 0) == -1) { | ||||||
|       SysExit(src, "nftw"); |       SysDie(src, "nftw"); | ||||||
|     } |     } | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  | @ -200,30 +188,31 @@ void Mv(char *src, char *dst) { | ||||||
|     dst = Join(dst, basename(src)); |     dst = Join(dst, basename(src)); | ||||||
|   } |   } | ||||||
|   if (!force && access(dst, W_OK) == -1 && errno != ENOENT) { |   if (!force && access(dst, W_OK) == -1 && errno != ENOENT) { | ||||||
|     SysExit(dst, "access"); |     SysDie(dst, "access"); | ||||||
|   } |   } | ||||||
|   strcpy(mkbuf, dst); |   strcpy(mkbuf, dst); | ||||||
|   if (makedirs((d = dirname(mkbuf)), 0755) == -1) { |   if (makedirs((d = dirname(mkbuf)), 0755) == -1) { | ||||||
|     SysExit(d, "makedirs"); |     SysDie(d, "makedirs"); | ||||||
|   } |   } | ||||||
|   if (IsSymlink(src)) { |   if (IsSymlink(src)) { | ||||||
|     if ((rc = readlink(src, linkbuf, sizeof(linkbuf) - 1)) == -1) { |     if ((rc = readlink(src, linkbuf, sizeof(linkbuf) - 1)) == -1) { | ||||||
|       SysExit(src, "readlink"); |       SysDie(src, "readlink"); | ||||||
|     } |     } | ||||||
|     linkbuf[rc] = 0; |     linkbuf[rc] = 0; | ||||||
|     if (symlink(linkbuf, dst)) { |     if (symlink(linkbuf, dst)) { | ||||||
|       SysExit(dst, "symlink"); |       SysDie(dst, "symlink"); | ||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     if (rename(src, dst)) { |     if (rename(src, dst)) { | ||||||
|       SysExit(src, "rename"); |       SysDie(src, "rename"); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   int i; |   int i; | ||||||
|   prog = argc > 0 ? argv[0] : "mv.com"; |   prog = argv[0]; | ||||||
|  |   if (!prog) prog = "mv"; | ||||||
|   GetOpts(argc, argv); |   GetOpts(argc, argv); | ||||||
|   if (argc - optind < 2) PrintUsage(1, 2); |   if (argc - optind < 2) PrintUsage(1, 2); | ||||||
|   for (i = optind; i < argc - 1; ++i) { |   for (i = optind; i < argc - 1; ++i) { | ||||||
|  |  | ||||||
|  | @ -1,79 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2022 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 "libc/calls/calls.h" |  | ||||||
| #include "libc/errno.h" |  | ||||||
| #include "libc/fmt/itoa.h" |  | ||||||
| #include "libc/fmt/magnumstrs.internal.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/o.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| 
 |  | ||||||
| char buf[512]; |  | ||||||
| 
 |  | ||||||
| static void Write(const char *s, ...) { |  | ||||||
|   va_list va; |  | ||||||
|   va_start(va, s); |  | ||||||
|   do { |  | ||||||
|     write(2, s, strlen(s)); |  | ||||||
|   } while ((s = va_arg(va, const char *))); |  | ||||||
|   va_end(va); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| wontreturn void SysExit(int rc, const char *call, const char *thing) { |  | ||||||
|   int err; |  | ||||||
|   char ibuf[12]; |  | ||||||
|   const char *estr; |  | ||||||
|   err = errno; |  | ||||||
|   FormatInt32(ibuf, err); |  | ||||||
|   estr = _strerdoc(err); |  | ||||||
|   if (!estr) estr = "EUNKNOWN"; |  | ||||||
|   Write(thing, ": ", call, "() failed: ", estr, " (", ibuf, ")\n", 0); |  | ||||||
|   exit(rc); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int i, opt; |  | ||||||
|   const char *outpath = "/dev/stdout"; |  | ||||||
|   while ((opt = getopt(argc, argv, "o:")) != -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case 'o': |  | ||||||
|         outpath = optarg; |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   int out = open(outpath, O_WRONLY | O_CREAT | O_TRUNC, 0644); |  | ||||||
|   if (out == -1) SysExit(2, "open", outpath); |  | ||||||
|   for (i = optind; i < argc; ++i) { |  | ||||||
|     int in = open(argv[i], O_RDONLY); |  | ||||||
|     if (in == -1) SysExit(3, "open", argv[i]); |  | ||||||
|     for (;;) { |  | ||||||
|       ssize_t rc = read(in, buf, 512); |  | ||||||
|       if (rc == -1) SysExit(3, "read", argv[i]); |  | ||||||
|       if (!rc) break; |  | ||||||
|       ssize_t rc2 = write(out, buf, rc); |  | ||||||
|       if (rc2 != rc) SysExit(4, "write", outpath); |  | ||||||
|     } |  | ||||||
|     if (close(in) == -1) SysExit(5, "close", argv[i]); |  | ||||||
|   } |  | ||||||
|   if (close(out) == -1) SysExit(6, "close", outpath); |  | ||||||
| } |  | ||||||
|  | @ -153,27 +153,15 @@ struct Relas { | ||||||
|   } * p; |   } * p; | ||||||
| } prtu; | } prtu; | ||||||
| 
 | 
 | ||||||
| nullterminated() static void Print(int fd, const char *s, ...) { |  | ||||||
|   va_list va; |  | ||||||
|   char buf[2048]; |  | ||||||
|   va_start(va, s); |  | ||||||
|   buf[0] = 0; |  | ||||||
|   do { |  | ||||||
|     strlcat(buf, s, sizeof(buf)); |  | ||||||
|   } while ((s = va_arg(va, const char *))); |  | ||||||
|   write(fd, buf, strlen(buf)); |  | ||||||
|   va_end(va); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static wontreturn void Die(const char *path, const char *reason) { | static wontreturn void Die(const char *path, const char *reason) { | ||||||
|   Print(2, path, ": ", reason, "\n", NULL); |   tinyprint(2, path, ": ", reason, "\n", NULL); | ||||||
|   exit(1); |   exit(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static wontreturn void SysExit(const char *path, const char *func) { | static wontreturn void SysExit(const char *path, const char *func) { | ||||||
|   const char *errstr; |   const char *errstr; | ||||||
|   if (!(errstr = _strerrno(errno))) errstr = "EUNKNOWN"; |   if (!(errstr = _strerrno(errno))) errstr = "EUNKNOWN"; | ||||||
|   Print(2, path, ": ", func, " failed with ", errstr, "\n", NULL); |   tinyprint(2, path, ": ", func, " failed with ", errstr, "\n", NULL); | ||||||
|   exit(1); |   exit(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -321,7 +309,7 @@ static void WritePackage(struct Package *pkg) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static wontreturn void PrintUsage(int fd, int exitcode) { | static wontreturn void PrintUsage(int fd, int exitcode) { | ||||||
|   Print(fd, "\n\
 |   tinyprint(fd, "\n\
 | ||||||
| NAME\n\ | NAME\n\ | ||||||
| \n\ | \n\ | ||||||
|   Cosmopolitan Monorepo Packager\n\ |   Cosmopolitan Monorepo Packager\n\ | ||||||
|  | @ -329,7 +317,7 @@ NAME\n\ | ||||||
| SYNOPSIS\n\ | SYNOPSIS\n\ | ||||||
| \n\ | \n\ | ||||||
|   ", |   ", | ||||||
|         program_invocation_name, " [FLAGS] OBJECT...\n\
 |             program_invocation_name, " [FLAGS] OBJECT...\n\
 | ||||||
| \n\ | \n\ | ||||||
| DESCRIPTION\n\ | DESCRIPTION\n\ | ||||||
| \n\ | \n\ | ||||||
|  | @ -345,7 +333,7 @@ FLAGS\n\ | ||||||
|   -d PATH       package dependency path [repeatable]\n\ |   -d PATH       package dependency path [repeatable]\n\ | ||||||
| \n\ | \n\ | ||||||
| ", | ", | ||||||
|         NULL); |             NULL); | ||||||
|   exit(exitcode); |   exit(exitcode); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -370,14 +358,15 @@ static void GetOpts(struct Package *pkg, struct Packages *deps, int argc, | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (pkg->path == -1) { |   if (pkg->path == -1) { | ||||||
|     Print(2, "error: no packages passed to package.com\n", NULL); |     tinyprint(2, "error: no packages passed to package.com\n", NULL); | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
|   if (optind == argc) { |   if (optind == argc) { | ||||||
|     Print(2, |     tinyprint( | ||||||
|           "no objects passed to package.com; is your foo.mk $(FOO_OBJS) glob " |         2, | ||||||
|           "broken?\n", |         "no objects passed to package.com; is your foo.mk $(FOO_OBJS) glob " | ||||||
|           NULL); |         "broken?\n", | ||||||
|  |         NULL); | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
|   getargs_init(&ga, argv + optind); |   getargs_init(&ga, argv + optind); | ||||||
|  | @ -495,7 +484,7 @@ static void LoadPriviligedRefsToUndefs(struct Package *pkg, | ||||||
|       if (obj->syms[x].st_shndx) continue;  // symbol is defined
 |       if (obj->syms[x].st_shndx) continue;  // symbol is defined
 | ||||||
|       if (ELF64_ST_BIND(obj->syms[x].st_info) != STB_WEAK && |       if (ELF64_ST_BIND(obj->syms[x].st_info) != STB_WEAK && | ||||||
|           ELF64_ST_BIND(obj->syms[x].st_info) != STB_GLOBAL) { |           ELF64_ST_BIND(obj->syms[x].st_info) != STB_GLOBAL) { | ||||||
|         Print(2, "warning: undefined symbol not global\n", NULL); |         tinyprint(2, "warning: undefined symbol not global\n", NULL); | ||||||
|         continue; |         continue; | ||||||
|       } |       } | ||||||
|       if (!(s = GetElfString(obj->elf, obj->size, obj->strs, |       if (!(s = GetElfString(obj->elf, obj->size, obj->strs, | ||||||
|  | @ -602,13 +591,13 @@ static void CheckStrictDeps(struct Package *pkg, struct Packages *deps) { | ||||||
|     undef = &pkg->undefs.p[i]; |     undef = &pkg->undefs.p[i]; | ||||||
|     if (undef->bind_ == STB_WEAK) continue; |     if (undef->bind_ == STB_WEAK) continue; | ||||||
|     if (!FindSymbol(pkg->strings.p + undef->name, pkg, deps, NULL, NULL)) { |     if (!FindSymbol(pkg->strings.p + undef->name, pkg, deps, NULL, NULL)) { | ||||||
|       Print(2, pkg->strings.p + pkg->path, ": undefined symbol '", |       tinyprint(2, pkg->strings.p + pkg->path, ": undefined symbol '", | ||||||
|             pkg->strings.p + undef->name, "' (", |                 pkg->strings.p + undef->name, "' (", | ||||||
|             pkg->strings.p + pkg->objects.p[undef->object].path, |                 pkg->strings.p + pkg->objects.p[undef->object].path, | ||||||
|             ") not defined by direct dependencies:\n", NULL); |                 ") not defined by direct dependencies:\n", NULL); | ||||||
|       for (j = 0; j < deps->i; ++j) { |       for (j = 0; j < deps->i; ++j) { | ||||||
|         dep = deps->p[j]; |         dep = deps->p[j]; | ||||||
|         Print(2, "\t", dep->strings.p + dep->path, "\n", NULL); |         tinyprint(2, "\t", dep->strings.p + dep->path, "\n", NULL); | ||||||
|       } |       } | ||||||
|       exit(1); |       exit(1); | ||||||
|     } |     } | ||||||
|  | @ -626,10 +615,11 @@ static void CheckYourPrivilege(struct Package *pkg, struct Packages *deps) { | ||||||
|     name = prtu.p[i].symbol_name; |     name = prtu.p[i].symbol_name; | ||||||
|     if (FindSymbol(name, pkg, deps, &dep, &sym) && |     if (FindSymbol(name, pkg, deps, &dep, &sym) && | ||||||
|         dep->sections.p[sym->section].kind == kText) { |         dep->sections.p[sym->section].kind == kText) { | ||||||
|       Print(2, prtu.p[i].object_path, |       tinyprint(2, prtu.p[i].object_path, | ||||||
|             ": privileged code referenced unprivileged symbol '", name, |                 ": privileged code referenced unprivileged symbol '", name, | ||||||
|             "' in section '", |                 "' in section '", | ||||||
|             dep->strings.p + dep->sections.p[sym->section].name, "'\n", NULL); |                 dep->strings.p + dep->sections.p[sym->section].name, "'\n", | ||||||
|  |                 NULL); | ||||||
|       ++f; |       ++f; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -119,9 +119,7 @@ int main(int argc, char *argv[]) { | ||||||
|       printf(U(argv[1]), argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); |       printf(U(argv[1]), argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); | ||||||
|       return 0; |       return 0; | ||||||
|     default: |     default: | ||||||
|       if (argc > 0) { |       fprintf(stderr, "%s: %s format [arguments]\n", argv[0], argv[0]); | ||||||
|         fprintf(stderr, "%s: %s format [arguments]\n", argv[0], argv[0]); |  | ||||||
|       } |  | ||||||
|       return 1; |       return 1; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,990 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2021 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 "libc/calls/calls.h" |  | ||||||
| #include "libc/calls/struct/sigaction.h" |  | ||||||
| #include "libc/calls/struct/sigset.h" |  | ||||||
| #include "libc/errno.h" |  | ||||||
| #include "libc/fmt/conv.h" |  | ||||||
| #include "libc/intrin/bits.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/log/log.h" |  | ||||||
| #include "libc/mem/gc.internal.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/exit.h" |  | ||||||
| #include "libc/sysv/consts/nr.h" |  | ||||||
| #include "libc/sysv/consts/o.h" |  | ||||||
| #include "libc/sysv/consts/sa.h" |  | ||||||
| #include "libc/sysv/consts/sig.h" |  | ||||||
| #include "libc/x/xasprintf.h" |  | ||||||
| #include "libc/x/xgetline.h" |  | ||||||
| #include "third_party/dlmalloc/dlmalloc.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * @fileoverview Pythonic System Call Trace |  | ||||||
|  * |  | ||||||
|  * This program invokes `strace` as a subprocess and turns its output |  | ||||||
|  * into Python data structures. It is useful because strace output is |  | ||||||
|  * this weird plaintext format that's so famously difficult to parse. |  | ||||||
|  * |  | ||||||
|  * For example, you can run this command: |  | ||||||
|  * |  | ||||||
|  *     pstrace -o trace.pylog echo hello world |  | ||||||
|  * |  | ||||||
|  * After which you may parse the output with Python: |  | ||||||
|  * |  | ||||||
|  *     for line in open('trace.pylog'): |  | ||||||
|  *       pid,time,elap,kind,x = eval(line) |  | ||||||
|  *       if kind == 1: |  | ||||||
|  *         name,ret,args = x |  | ||||||
|  *         print "%s%r -> %d" % (name, args, ret) |  | ||||||
|  * |  | ||||||
|  * This program traces the subset of system calls governing processes |  | ||||||
|  * and files. To do that we must track file descriptor lifetimes too. |  | ||||||
|  * We also track system calls that are problematic for build configs, |  | ||||||
|  * such as sockets, since compiling code shouldn't need the Internet. |  | ||||||
|  * |  | ||||||
|  * @note this tool is linux only |  | ||||||
|  * @note freebsd: truss PROC ARGS |  | ||||||
|  * @note appleos: sudo dtruss PROC ARGS |  | ||||||
|  * @note openbsd: ktrace PROC ARGS && kdump -f ktrace.out |  | ||||||
|  * @note windows: https://github.com/rogerorr/NtTrace
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #define DEBUG        "%ld: %s", lineno, line |  | ||||||
| #define READ128BE(S) ((uint128_t)READ64BE(S) << 64 | READ64BE((S) + 8)) |  | ||||||
| #define APPEND(L)                             \ |  | ||||||
|   do {                                        \ |  | ||||||
|     if (++L.n > L.c) {                        \ |  | ||||||
|       L.c = MAX(11, L.c);                     \ |  | ||||||
|       L.c += L.c >> 1;                        \ |  | ||||||
|       L.p = realloc(L.p, L.c * sizeof(*L.p)); \ |  | ||||||
|     }                                         \ |  | ||||||
|     bzero(L.p + L.n - 1, sizeof(*L.p));       \ |  | ||||||
|   } while (0) |  | ||||||
| 
 |  | ||||||
| struct Trace { |  | ||||||
|   struct Slices { |  | ||||||
|     long n, c; |  | ||||||
|     struct Slice { |  | ||||||
|       int n, c; |  | ||||||
|       char *p; |  | ||||||
|     } * p; |  | ||||||
|   } slices; |  | ||||||
|   struct HashTable { |  | ||||||
|     long i, n; |  | ||||||
|     struct HashEntry { |  | ||||||
|       long h; |  | ||||||
|       long i; |  | ||||||
|     } * p; |  | ||||||
|   } sliceindex; |  | ||||||
|   struct Strlists { |  | ||||||
|     long n, c; |  | ||||||
|     struct Strlist { |  | ||||||
|       long n, c; |  | ||||||
|       long *p;  // slices.p[p[i]]
 |  | ||||||
|     } * p; |  | ||||||
|   } strlists; |  | ||||||
|   struct Events { |  | ||||||
|     long n, c; |  | ||||||
|     struct Event { |  | ||||||
|       enum EventKind { |  | ||||||
|         EK_NONE, |  | ||||||
|         EK_CALL, |  | ||||||
|         EK_EXIT,    // ret is kernel code
 |  | ||||||
|         EK_SIGNAL,  // ret is signal code
 |  | ||||||
|         EK_KILLED,  // ret is signal code
 |  | ||||||
|       } kind; |  | ||||||
|       unsigned char arity; |  | ||||||
|       unsigned char syscall_; |  | ||||||
|       bool is_interrupted; |  | ||||||
|       int us; |  | ||||||
|       int elap; |  | ||||||
|       int pid; |  | ||||||
|       long sec; |  | ||||||
|       long ret; |  | ||||||
|       long lineno; |  | ||||||
|       struct Arg { |  | ||||||
|         enum ArgKind { |  | ||||||
|           AK_LONG,     // x
 |  | ||||||
|           AK_STR,      // slices.p[x]
 |  | ||||||
|           AK_STRLIST,  // strlists.p[x]
 |  | ||||||
|           AK_INTPAIR,  // (x&0xffffffff, x>>32)
 |  | ||||||
|         } kind; |  | ||||||
|         long name; |  | ||||||
|         long x; |  | ||||||
|       } arg[6]; |  | ||||||
|     } * p; |  | ||||||
|   } events; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const struct Syscall { |  | ||||||
|   char name[16]; |  | ||||||
| } kSyscalls[] = { |  | ||||||
|     {"accept"},          //
 |  | ||||||
|     {"accept4"},         //
 |  | ||||||
|     {"access"},          //
 |  | ||||||
|     {"bind"},            //
 |  | ||||||
|     {"chdir"},           //
 |  | ||||||
|     {"chmod"},           //
 |  | ||||||
|     {"chown"},           //
 |  | ||||||
|     {"chroot"},          //
 |  | ||||||
|     {"clone"},           //
 |  | ||||||
|     {"close"},           //
 |  | ||||||
|     {"connect"},         //
 |  | ||||||
|     {"creat"},           //
 |  | ||||||
|     {"dup"},             //
 |  | ||||||
|     {"dup2"},            //
 |  | ||||||
|     {"dup3"},            //
 |  | ||||||
|     {"epoll_create"},    //
 |  | ||||||
|     {"epoll_create1"},   //
 |  | ||||||
|     {"eventfd"},         //
 |  | ||||||
|     {"eventfd2"},        //
 |  | ||||||
|     {"execve"},          //
 |  | ||||||
|     {"execveat"},        //
 |  | ||||||
|     {"faccessat"},       //
 |  | ||||||
|     {"fchmodat"},        //
 |  | ||||||
|     {"fchownat"},        //
 |  | ||||||
|     {"fdatasync"},       //
 |  | ||||||
|     {"fcntl"},           //
 |  | ||||||
|     {"flock"},           //
 |  | ||||||
|     {"fork"},            //
 |  | ||||||
|     {"fsync"},           //
 |  | ||||||
|     {"lchown"},          //
 |  | ||||||
|     {"link"},            //
 |  | ||||||
|     {"linkat"},          //
 |  | ||||||
|     {"listen"},          //
 |  | ||||||
|     {"memfd_create"},    //
 |  | ||||||
|     {"mkdir"},           //
 |  | ||||||
|     {"mkdirat"},         //
 |  | ||||||
|     {"mknod"},           //
 |  | ||||||
|     {"mknodat"},         //
 |  | ||||||
|     {"open"},            //
 |  | ||||||
|     {"openat"},          //
 |  | ||||||
|     {"pipe"},            //
 |  | ||||||
|     {"pipe2"},           //
 |  | ||||||
|     {"readlink"},        //
 |  | ||||||
|     {"readlinkat"},      //
 |  | ||||||
|     {"rename"},          //
 |  | ||||||
|     {"renameat"},        //
 |  | ||||||
|     {"renameat2"},       //
 |  | ||||||
|     {"rmdir"},           //
 |  | ||||||
|     {"signalfd"},        //
 |  | ||||||
|     {"signalfd4"},       //
 |  | ||||||
|     {"socket"},          //
 |  | ||||||
|     {"socketpair"},      //
 |  | ||||||
|     {"statfs"},          //
 |  | ||||||
|     {"symlink"},         //
 |  | ||||||
|     {"symlinkat"},       //
 |  | ||||||
|     {"sync"},            //
 |  | ||||||
|     {"syncfs"},          //
 |  | ||||||
|     {"timerfd_create"},  //
 |  | ||||||
|     {"truncate"},        //
 |  | ||||||
|     {"unlink"},          //
 |  | ||||||
|     {"unlinkat"},        //
 |  | ||||||
|     {"utimensat"},       //
 |  | ||||||
|     {"vfork"},           //
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const struct Signal { |  | ||||||
|   char name[8]; |  | ||||||
|   unsigned char number; |  | ||||||
| } kSignals[] = { |  | ||||||
|     {"SIGABRT", 6},    //
 |  | ||||||
|     {"SIGALRM", 14},   //
 |  | ||||||
|     {"SIGBUS", 7},     //
 |  | ||||||
|     {"SIGCHLD", 17},   //
 |  | ||||||
|     {"SIGCONT", 18},   //
 |  | ||||||
|     {"SIGFPE", 8},     //
 |  | ||||||
|     {"SIGHUP", 1},     //
 |  | ||||||
|     {"SIGILL", 4},     //
 |  | ||||||
|     {"SIGINT", 2},     //
 |  | ||||||
|     {"SIGIO", 29},     //
 |  | ||||||
|     {"SIGIOT", 6},     //
 |  | ||||||
|     {"SIGKILL", 9},    //
 |  | ||||||
|     {"SIGPIPE", 13},   //
 |  | ||||||
|     {"SIGPOLL", 29},   //
 |  | ||||||
|     {"SIGPROF", 27},   //
 |  | ||||||
|     {"SIGPWR", 30},    //
 |  | ||||||
|     {"SIGQUIT", 3},    //
 |  | ||||||
|     {"SIGSEGV", 11},   //
 |  | ||||||
|     {"SIGSTOP", 19},   //
 |  | ||||||
|     {"SIGSYS", 31},    //
 |  | ||||||
|     {"SIGTERM", 15},   //
 |  | ||||||
|     {"SIGTRAP", 5},    //
 |  | ||||||
|     {"SIGTSTP", 20},   //
 |  | ||||||
|     {"SIGTTIN", 21},   //
 |  | ||||||
|     {"SIGTTOU", 22},   //
 |  | ||||||
|     {"SIGURG", 23},    //
 |  | ||||||
|     {"SIGUSR1", 10},   //
 |  | ||||||
|     {"SIGUSR2", 12},   //
 |  | ||||||
|     {"SIGWINCH", 28},  //
 |  | ||||||
|     {"SIGXCPU", 24},   //
 |  | ||||||
|     {"SIGXFSZ", 25},   //
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const struct Errno { |  | ||||||
|   char name[16]; |  | ||||||
|   unsigned char number; |  | ||||||
| } kErrnos[] = { |  | ||||||
|     {"E2BIG", 7},              //
 |  | ||||||
|     {"EACCES", 13},            //
 |  | ||||||
|     {"EADDRINUSE", 98},        //
 |  | ||||||
|     {"EADDRNOTAVAIL", 99},     //
 |  | ||||||
|     {"EADV", 68},              //
 |  | ||||||
|     {"EAFNOSUPPORT", 97},      //
 |  | ||||||
|     {"EAGAIN", 11},            //
 |  | ||||||
|     {"EALREADY", 114},         //
 |  | ||||||
|     {"EBADE", 52},             //
 |  | ||||||
|     {"EBADF", 9},              //
 |  | ||||||
|     {"EBADFD", 77},            //
 |  | ||||||
|     {"EBADMSG", 74},           //
 |  | ||||||
|     {"EBADR", 53},             //
 |  | ||||||
|     {"EBADRQC", 56},           //
 |  | ||||||
|     {"EBADSLT", 57},           //
 |  | ||||||
|     {"EBFONT", 59},            //
 |  | ||||||
|     {"EBUSY", 16},             //
 |  | ||||||
|     {"ECANCELED", 125},        //
 |  | ||||||
|     {"ECHILD", 10},            //
 |  | ||||||
|     {"ECHRNG", 44},            //
 |  | ||||||
|     {"ECOMM", 70},             //
 |  | ||||||
|     {"ECONNABORTED", 103},     //
 |  | ||||||
|     {"ECONNREFUSED", 111},     //
 |  | ||||||
|     {"ECONNRESET", 104},       //
 |  | ||||||
|     {"EDEADLK", 35},           //
 |  | ||||||
|     {"EDESTADDRREQ", 89},      //
 |  | ||||||
|     {"EDOM", 33},              //
 |  | ||||||
|     {"EDOTDOT", 73},           //
 |  | ||||||
|     {"EDQUOT", 122},           //
 |  | ||||||
|     {"EEXIST", 17},            //
 |  | ||||||
|     {"EFAULT", 14},            //
 |  | ||||||
|     {"EFBIG", 27},             //
 |  | ||||||
|     {"EHOSTDOWN", 112},        //
 |  | ||||||
|     {"EHOSTUNREACH", 113},     //
 |  | ||||||
|     {"EHWPOISON", 133},        //
 |  | ||||||
|     {"EIDRM", 43},             //
 |  | ||||||
|     {"EILSEQ", 84},            //
 |  | ||||||
|     {"EINPROGRESS", 115},      //
 |  | ||||||
|     {"EINTR", 4},              //
 |  | ||||||
|     {"EINVAL", 22},            //
 |  | ||||||
|     {"EIO", 5},                //
 |  | ||||||
|     {"EISCONN", 106},          //
 |  | ||||||
|     {"EISDIR", 21},            //
 |  | ||||||
|     {"EISNAM", 120},           //
 |  | ||||||
|     {"EKEYEXPIRED", 127},      //
 |  | ||||||
|     {"EKEYREJECTED", 129},     //
 |  | ||||||
|     {"EKEYREVOKED", 128},      //
 |  | ||||||
|     {"EL2HLT", 51},            //
 |  | ||||||
|     {"EL2NSYNC", 45},          //
 |  | ||||||
|     {"EL3HLT", 46},            //
 |  | ||||||
|     {"EL3RST", 47},            //
 |  | ||||||
|     {"ELIBACC", 79},           //
 |  | ||||||
|     {"ELIBBAD", 80},           //
 |  | ||||||
|     {"ELIBEXEC", 83},          //
 |  | ||||||
|     {"ELIBMAX", 82},           //
 |  | ||||||
|     {"ELIBSCN", 81},           //
 |  | ||||||
|     {"ELNRNG", 48},            //
 |  | ||||||
|     {"ELOOP", 40},             //
 |  | ||||||
|     {"EMEDIUMTYPE", 124},      //
 |  | ||||||
|     {"EMFILE", 24},            //
 |  | ||||||
|     {"EMLINK", 31},            //
 |  | ||||||
|     {"EMSGSIZE", 90},          //
 |  | ||||||
|     {"EMULTIHOP", 72},         //
 |  | ||||||
|     {"ENAMETOOLONG", 36},      //
 |  | ||||||
|     {"ENAVAIL", 119},          //
 |  | ||||||
|     {"ENETDOWN", 100},         //
 |  | ||||||
|     {"ENETRESET", 102},        //
 |  | ||||||
|     {"ENETUNREACH", 101},      //
 |  | ||||||
|     {"ENFILE", 23},            //
 |  | ||||||
|     {"ENOANO", 55},            //
 |  | ||||||
|     {"ENOBUFS", 105},          //
 |  | ||||||
|     {"ENOCSI", 50},            //
 |  | ||||||
|     {"ENODATA", 61},           //
 |  | ||||||
|     {"ENODEV", 19},            //
 |  | ||||||
|     {"ENOENT", 2},             //
 |  | ||||||
|     {"ENOEXEC", 8},            //
 |  | ||||||
|     {"ENOKEY", 126},           //
 |  | ||||||
|     {"ENOLCK", 37},            //
 |  | ||||||
|     {"ENOLINK", 67},           //
 |  | ||||||
|     {"ENOMEDIUM", 123},        //
 |  | ||||||
|     {"ENOMEM", 12},            //
 |  | ||||||
|     {"ENOMSG", 42},            //
 |  | ||||||
|     {"ENONET", 64},            //
 |  | ||||||
|     {"ENOPKG", 65},            //
 |  | ||||||
|     {"ENOPROTOOPT", 92},       //
 |  | ||||||
|     {"ENOSPC", 28},            //
 |  | ||||||
|     {"ENOSR", 63},             //
 |  | ||||||
|     {"ENOSTR", 60},            //
 |  | ||||||
|     {"ENOSYS", 38},            //
 |  | ||||||
|     {"ENOTBLK", 15},           //
 |  | ||||||
|     {"ENOTCONN", 107},         //
 |  | ||||||
|     {"ENOTDIR", 20},           //
 |  | ||||||
|     {"ENOTEMPTY", 39},         //
 |  | ||||||
|     {"ENOTNAM", 118},          //
 |  | ||||||
|     {"ENOTRECOVERABLE", 131},  //
 |  | ||||||
|     {"ENOTSOCK", 88},          //
 |  | ||||||
|     {"ENOTSUP", 95},           //
 |  | ||||||
|     {"ENOTTY", 25},            //
 |  | ||||||
|     {"ENOTUNIQ", 76},          //
 |  | ||||||
|     {"ENXIO", 6},              //
 |  | ||||||
|     {"EOPNOTSUPP", 95},        //
 |  | ||||||
|     {"EOVERFLOW", 75},         //
 |  | ||||||
|     {"EOWNERDEAD", 130},       //
 |  | ||||||
|     {"EPERM", 1},              //
 |  | ||||||
|     {"EPFNOSUPPORT", 96},      //
 |  | ||||||
|     {"EPIPE", 32},             //
 |  | ||||||
|     {"EPROTO", 71},            //
 |  | ||||||
|     {"EPROTONOSUPPORT", 93},   //
 |  | ||||||
|     {"EPROTOTYPE", 91},        //
 |  | ||||||
|     {"ERANGE", 34},            //
 |  | ||||||
|     {"EREMCHG", 78},           //
 |  | ||||||
|     {"EREMOTE", 66},           //
 |  | ||||||
|     {"EREMOTEIO", 121},        //
 |  | ||||||
|     {"ERESTART", 85},          //
 |  | ||||||
|     {"ERFKILL", 132},          //
 |  | ||||||
|     {"EROFS", 30},             //
 |  | ||||||
|     {"ESHUTDOWN", 108},        //
 |  | ||||||
|     {"ESOCKTNOSUPPORT", 94},   //
 |  | ||||||
|     {"ESPIPE", 29},            //
 |  | ||||||
|     {"ESRCH", 3},              //
 |  | ||||||
|     {"ESRMNT", 69},            //
 |  | ||||||
|     {"ESTALE", 116},           //
 |  | ||||||
|     {"ESTRPIPE", 86},          //
 |  | ||||||
|     {"ETIME", 62},             //
 |  | ||||||
|     {"ETIMEDOUT", 110},        //
 |  | ||||||
|     {"ETOOMANYREFS", 109},     //
 |  | ||||||
|     {"ETXTBSY", 26},           //
 |  | ||||||
|     {"EUCLEAN", 117},          //
 |  | ||||||
|     {"EUNATCH", 49},           //
 |  | ||||||
|     {"EUSERS", 87},            //
 |  | ||||||
|     {"EWOULDBLOCK", 11},       //
 |  | ||||||
|     {"EXDEV", 18},             //
 |  | ||||||
|     {"EXFULL", 54},            //
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static char **strace_args; |  | ||||||
| static size_t strace_args_len; |  | ||||||
| static volatile bool interrupted; |  | ||||||
| 
 |  | ||||||
| static long Hash(const void *p, size_t n) { |  | ||||||
|   unsigned h, i; |  | ||||||
|   for (h = i = 0; i < n; i++) { |  | ||||||
|     h += ((unsigned char *)p)[i]; |  | ||||||
|     h *= 0x9e3779b1; |  | ||||||
|   } |  | ||||||
|   return MAX(1, h); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static uint64_t MakeKey64(const char *p, size_t n) { |  | ||||||
|   char k[8] = {0}; |  | ||||||
|   memcpy(k, p, n); |  | ||||||
|   return READ64BE(k); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static uint128_t MakeKey128(const char *p, size_t n) { |  | ||||||
|   char k[16] = {0}; |  | ||||||
|   memcpy(k, p, n); |  | ||||||
|   return READ128BE(k); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int GetSyscall(const char *name, size_t namelen) { |  | ||||||
|   int m, l, r; |  | ||||||
|   uint128_t x, y; |  | ||||||
|   char *endofname; |  | ||||||
|   if (namelen && namelen <= 16) { |  | ||||||
|     x = MakeKey128(name, namelen); |  | ||||||
|     l = 0; |  | ||||||
|     r = ARRAYLEN(kSyscalls) - 1; |  | ||||||
|     while (l <= r) { |  | ||||||
|       m = (l + r) >> 1; |  | ||||||
|       y = READ128BE(kSyscalls[m].name); |  | ||||||
|       if (x < y) { |  | ||||||
|         r = m - 1; |  | ||||||
|       } else if (x > y) { |  | ||||||
|         l = m + 1; |  | ||||||
|       } else { |  | ||||||
|         return m; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int GetErrno(const char *name, size_t namelen) { |  | ||||||
|   int m, l, r; |  | ||||||
|   uint128_t x, y; |  | ||||||
|   char *endofname; |  | ||||||
|   if (namelen && namelen <= 16) { |  | ||||||
|     x = MakeKey128(name, namelen); |  | ||||||
|     l = 0; |  | ||||||
|     r = ARRAYLEN(kErrnos) - 1; |  | ||||||
|     while (l <= r) { |  | ||||||
|       m = (l + r) >> 1; |  | ||||||
|       y = READ128BE(kErrnos[m].name); |  | ||||||
|       if (x < y) { |  | ||||||
|         r = m - 1; |  | ||||||
|       } else if (x > y) { |  | ||||||
|         l = m + 1; |  | ||||||
|       } else { |  | ||||||
|         return kErrnos[m].number; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int GetSignal(const char *name, size_t namelen) { |  | ||||||
|   int m, l, r; |  | ||||||
|   uint64_t x, y; |  | ||||||
|   char *endofname; |  | ||||||
|   if (namelen && namelen <= 8) { |  | ||||||
|     x = MakeKey64(name, namelen); |  | ||||||
|     l = 0; |  | ||||||
|     r = ARRAYLEN(kSignals) - 1; |  | ||||||
|     while (l <= r) { |  | ||||||
|       m = (l + r) >> 1; |  | ||||||
|       y = READ64BE(kSignals[m].name); |  | ||||||
|       if (x < y) { |  | ||||||
|         r = m - 1; |  | ||||||
|       } else if (x > y) { |  | ||||||
|         l = m + 1; |  | ||||||
|       } else { |  | ||||||
|         return kSignals[m].number; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static struct Trace *NewTrace(void) { |  | ||||||
|   return calloc(1, sizeof(struct Trace)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void FreeTrace(struct Trace *t) { |  | ||||||
|   long i; |  | ||||||
|   if (t) { |  | ||||||
|     for (i = 0; i < t->slices.n; ++i) { |  | ||||||
|       free(t->slices.p[i].p); |  | ||||||
|     } |  | ||||||
|     free(t->slices.p); |  | ||||||
|     free(t->sliceindex.p); |  | ||||||
|     for (i = 0; i < t->strlists.n; ++i) { |  | ||||||
|       free(t->strlists.p[i].p); |  | ||||||
|     } |  | ||||||
|     free(t->strlists.p); |  | ||||||
|     free(t->events.p); |  | ||||||
|     free(t); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void AppendStrlists(struct Trace *t) { |  | ||||||
|   APPEND(t->strlists); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void AppendStrlist(struct Strlist *l) { |  | ||||||
|   APPEND((*l)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void AppendEvent(struct Trace *t) { |  | ||||||
|   APPEND(t->events); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void AppendSlices(struct Trace *t) { |  | ||||||
|   APPEND(t->slices); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void AppendSlice(struct Slice *s, int c) { |  | ||||||
|   APPEND((*s)); |  | ||||||
|   s->p[s->n - 1] = c; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static long Intern(struct Trace *t, char *data, long size) { |  | ||||||
|   struct HashEntry *p; |  | ||||||
|   long i, j, k, n, m, h, n2; |  | ||||||
|   h = Hash(data, size); |  | ||||||
|   n = t->sliceindex.n; |  | ||||||
|   i = 0; |  | ||||||
|   if (n) { |  | ||||||
|     k = 0; |  | ||||||
|     do { |  | ||||||
|       i = (h + k + ((k + 1) >> 1)) & (n - 1); |  | ||||||
|       if (t->sliceindex.p[i].h == h && |  | ||||||
|           t->slices.p[t->sliceindex.p[i].i].n == size && |  | ||||||
|           !memcmp(t->slices.p[t->sliceindex.p[i].i].p, data, size)) { |  | ||||||
|         free(data); |  | ||||||
|         return t->sliceindex.p[i].i; |  | ||||||
|       } |  | ||||||
|       ++k; |  | ||||||
|     } while (t->sliceindex.p[i].h); |  | ||||||
|   } |  | ||||||
|   if (++t->sliceindex.i >= (n >> 1)) { |  | ||||||
|     m = n ? n << 1 : 16; |  | ||||||
|     p = calloc(m, sizeof(struct HashEntry)); |  | ||||||
|     for (j = 0; j < n; ++j) { |  | ||||||
|       if (t->sliceindex.p[j].h) { |  | ||||||
|         k = 0; |  | ||||||
|         do { |  | ||||||
|           i = (t->sliceindex.p[j].h + k + ((k + 1) >> 1)) & (m - 1); |  | ||||||
|           ++k; |  | ||||||
|         } while (p[i].h); |  | ||||||
|         p[i].h = t->sliceindex.p[j].h; |  | ||||||
|         p[i].i = t->sliceindex.p[j].i; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     k = 0; |  | ||||||
|     do { |  | ||||||
|       i = (h + k + ((k + 1) >> 1)) & (m - 1); |  | ||||||
|       ++k; |  | ||||||
|     } while (p[i].h); |  | ||||||
|     free(t->sliceindex.p); |  | ||||||
|     t->sliceindex.p = p; |  | ||||||
|     t->sliceindex.n = m; |  | ||||||
|   } |  | ||||||
|   AppendSlices(t); |  | ||||||
|   t->slices.p[t->slices.n - 1].p = data; |  | ||||||
|   t->slices.p[t->slices.n - 1].n = size; |  | ||||||
|   t->sliceindex.p[i].i = t->slices.n - 1; |  | ||||||
|   t->sliceindex.p[i].h = h; |  | ||||||
|   return t->slices.n - 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static long ReadCharLiteral(struct Slice *buf, long c, char *p, long *i) { |  | ||||||
|   if (c != '\\') return c; |  | ||||||
|   switch ((c = p[(*i)++])) { |  | ||||||
|     case 'a': |  | ||||||
|       return '\a'; |  | ||||||
|     case 'b': |  | ||||||
|       return '\b'; |  | ||||||
|     case 't': |  | ||||||
|       return '\t'; |  | ||||||
|     case 'n': |  | ||||||
|       return '\n'; |  | ||||||
|     case 'v': |  | ||||||
|       return '\v'; |  | ||||||
|     case 'f': |  | ||||||
|       return '\f'; |  | ||||||
|     case 'r': |  | ||||||
|       return '\r'; |  | ||||||
|     case 'e': |  | ||||||
|       return 033; |  | ||||||
|     case 'x': |  | ||||||
|       if (isxdigit(p[*i])) { |  | ||||||
|         c = hextoint(p[(*i)++]); |  | ||||||
|         if (isxdigit(p[*i])) { |  | ||||||
|           c = c * 16 + hextoint(p[(*i)++]); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       return c; |  | ||||||
|     case '0': |  | ||||||
|     case '1': |  | ||||||
|     case '2': |  | ||||||
|     case '3': |  | ||||||
|     case '4': |  | ||||||
|     case '5': |  | ||||||
|     case '6': |  | ||||||
|     case '7': |  | ||||||
|       c -= '0'; |  | ||||||
|       if ('0' <= p[*i] && p[*i] <= '7') { |  | ||||||
|         c = c * 8 + (p[(*i)++] - '0'); |  | ||||||
|         if ('0' <= p[*i] && p[*i] <= '7') { |  | ||||||
|           c = c * 8 + (p[(*i)++] - '0'); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       return c; |  | ||||||
|     default: |  | ||||||
|       return c; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static long GetDuration(long sec1, long us1, long sec2, long us2) { |  | ||||||
|   long elap; |  | ||||||
|   if ((elap = (sec2 - sec1) * 1000000)) { |  | ||||||
|     return elap + 1000000 - us1 + us2; |  | ||||||
|   } else { |  | ||||||
|     return elap + us2 - us1; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void Parse(struct Trace *t, const char *line, long lineno) { |  | ||||||
|   char *p, *q; |  | ||||||
|   struct Slice b; |  | ||||||
|   long c, i, j, k, arg, pid, event, sec, us; |  | ||||||
|   p = line; |  | ||||||
|   pid = strtol(p, &p, 10); |  | ||||||
|   while (*p == ' ') ++p; |  | ||||||
|   sec = strtol(p, &p, 10); |  | ||||||
|   CHECK_EQ('.', *p++, DEBUG); |  | ||||||
|   us = strtol(p, &p, 10); |  | ||||||
|   CHECK_EQ(' ', *p++, DEBUG); |  | ||||||
|   if (_startswith(p, "<... ")) { |  | ||||||
|     CHECK_NOTNULL((p = strchr(p, '>'))); |  | ||||||
|     ++p; |  | ||||||
|     for (event = t->events.n; event--;) { |  | ||||||
|       if (t->events.p[event].pid == pid) { |  | ||||||
|         CHECK(t->events.p[event].is_interrupted, DEBUG); |  | ||||||
|         t->events.p[event].is_interrupted = false; |  | ||||||
|         t->events.p[event].elap = |  | ||||||
|             GetDuration(t->events.p[event].sec, t->events.p[event].us, sec, us); |  | ||||||
|         break; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     CHECK_GE(event, 0); |  | ||||||
|   } else { |  | ||||||
|     AppendEvent(t); |  | ||||||
|     event = t->events.n - 1; |  | ||||||
|     t->events.p[event].pid = pid; |  | ||||||
|     t->events.p[event].sec = sec; |  | ||||||
|     t->events.p[event].us = us; |  | ||||||
|     t->events.p[event].lineno = lineno; |  | ||||||
|     if (_startswith(p, "+++ exited with ")) { |  | ||||||
|       p += strlen("+++ exited with "); |  | ||||||
|       t->events.p[event].kind = EK_EXIT; |  | ||||||
|       t->events.p[event].ret = atoi(p); |  | ||||||
|       return; |  | ||||||
|     } else if (_startswith(p, "+++ killed by ")) { |  | ||||||
|       p += strlen("+++ killed by "); |  | ||||||
|       CHECK((q = strchr(p, ' ')), DEBUG); |  | ||||||
|       t->events.p[event].kind = EK_KILLED; |  | ||||||
|       t->events.p[event].ret = GetSignal(p, q - p); |  | ||||||
|       return; |  | ||||||
|     } else if (_startswith(p, "--- ")) { |  | ||||||
|       p += 4; |  | ||||||
|       CHECK(isalpha(*p), DEBUG); |  | ||||||
|       CHECK((q = strchr(p, ' ')), DEBUG); |  | ||||||
|       t->events.p[event].kind = EK_SIGNAL; |  | ||||||
|       t->events.p[event].ret = GetSignal(p, q - p); |  | ||||||
|       return; |  | ||||||
|     } else if (isalpha(*p) && (q = strchr(p, '('))) { |  | ||||||
|       t->events.p[event].kind = EK_CALL; |  | ||||||
|       CHECK_NE(-1, (t->events.p[event].syscall_ = GetSyscall(p, q - p)), DEBUG); |  | ||||||
|       p = q + 1; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   for (;;) { |  | ||||||
|     if (*p == ',') ++p; |  | ||||||
|     while (*p == ' ') ++p; |  | ||||||
|     CHECK(*p, DEBUG); |  | ||||||
|     if (_startswith(p, "<unfinished ...>")) { |  | ||||||
|       t->events.p[event].is_interrupted = true; |  | ||||||
|       break; |  | ||||||
|     } else if (*p == ')') { |  | ||||||
|       ++p; |  | ||||||
|       while (isspace(*p)) ++p; |  | ||||||
|       CHECK_EQ('=', *p++, DEBUG); |  | ||||||
|       while (isspace(*p)) ++p; |  | ||||||
|       CHECK(isdigit(*p) || *p == '-', DEBUG); |  | ||||||
|       t->events.p[event].ret = strtol(p, &p, 0); |  | ||||||
|       if (t->events.p[event].ret == -1) { |  | ||||||
|         while (isspace(*p)) ++p; |  | ||||||
|         CHECK((q = strchr(p, ' ')), DEBUG); |  | ||||||
|         if ((t->events.p[event].ret = GetErrno(p, q - p)) != -1) { |  | ||||||
|           t->events.p[event].ret = -t->events.p[event].ret; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|     CHECK_LT((arg = t->events.p[event].arity++), 6); |  | ||||||
|     if (isalpha(*p) && !_startswith(p, "NULL")) { |  | ||||||
|       bzero(&b, sizeof(b)); |  | ||||||
|       for (; isalpha(*p) || *p == '_'; ++p) { |  | ||||||
|         AppendSlice(&b, *p); |  | ||||||
|       } |  | ||||||
|       t->events.p[event].arg[arg].name = Intern(t, b.p, b.n); |  | ||||||
|       CHECK_EQ('=', *p++, DEBUG); |  | ||||||
|     } else { |  | ||||||
|       t->events.p[event].arg[arg].name = -1; |  | ||||||
|     } |  | ||||||
|     if (_startswith(p, "NULL")) { |  | ||||||
|       p += 4; |  | ||||||
|       t->events.p[event].arg[arg].kind = AK_LONG; |  | ||||||
|       t->events.p[event].arg[arg].x = 0; |  | ||||||
|     } else if (*p == '-' || isdigit(*p)) { |  | ||||||
|       t->events.p[event].arg[arg].kind = AK_LONG; |  | ||||||
|       for (;;) { |  | ||||||
|         t->events.p[event].arg[arg].x |= strtol(p, &p, 0); |  | ||||||
|         if (*p == '|') { |  | ||||||
|           ++p; |  | ||||||
|         } else { |  | ||||||
|           break; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } else if (*p == '{') { |  | ||||||
|       CHECK_NOTNULL((p = strchr(p, '}')), DEBUG); |  | ||||||
|       ++p; |  | ||||||
|     } else if (*p == '"') { |  | ||||||
|       bzero(&b, sizeof(b)); |  | ||||||
|       for (j = 0; (c = p[++j]);) { |  | ||||||
|         if (c == '"') { |  | ||||||
|           p += j + 1; |  | ||||||
|           break; |  | ||||||
|         } |  | ||||||
|         c = ReadCharLiteral(&b, c, p, &j); |  | ||||||
|         AppendSlice(&b, c); |  | ||||||
|       } |  | ||||||
|       t->events.p[event].arg[arg].kind = AK_STR; |  | ||||||
|       t->events.p[event].arg[arg].x = Intern(t, b.p, b.n); |  | ||||||
|     } else if (*p == '[') { |  | ||||||
|       ++p; |  | ||||||
|       if (isdigit(*p)) { |  | ||||||
|         t->events.p[event].arg[arg].kind = AK_INTPAIR; |  | ||||||
|         t->events.p[event].arg[arg].x = strtol(p, &p, 0) & 0xffffffff; |  | ||||||
|         CHECK_EQ(',', *p++, DEBUG); |  | ||||||
|         CHECK_EQ(' ', *p++, DEBUG); |  | ||||||
|         t->events.p[event].arg[arg].x |= strtol(p, &p, 0) << 32; |  | ||||||
|         CHECK_EQ(']', *p++, DEBUG); |  | ||||||
|       } else { |  | ||||||
|         AppendStrlists(t); |  | ||||||
|         for (j = 0;; ++j) { |  | ||||||
|           if (*p == ']') { |  | ||||||
|             ++p; |  | ||||||
|             break; |  | ||||||
|           } |  | ||||||
|           if (*p == ',') ++p; |  | ||||||
|           if (*p == ' ') ++p; |  | ||||||
|           CHECK_EQ('"', *p, DEBUG); |  | ||||||
|           bzero(&b, sizeof(b)); |  | ||||||
|           for (k = 0; (c = p[++k]);) { |  | ||||||
|             if (c == '"') { |  | ||||||
|               p += k + 1; |  | ||||||
|               break; |  | ||||||
|             } |  | ||||||
|             c = ReadCharLiteral(&b, c, p, &k); |  | ||||||
|             AppendSlice(&b, c); |  | ||||||
|           } |  | ||||||
|           AppendStrlist(&t->strlists.p[t->strlists.n - 1]); |  | ||||||
|           t->strlists.p[t->strlists.n - 1] |  | ||||||
|               .p[t->strlists.p[t->strlists.n - 1].n - 1] = Intern(t, b.p, b.n); |  | ||||||
|         } |  | ||||||
|         t->events.p[event].arg[arg].kind = AK_STRLIST; |  | ||||||
|         t->events.p[event].arg[arg].x = t->strlists.n - 1; |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       CHECK(false, DEBUG); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void PrintArg(FILE *f, struct Trace *t, long ev, long arg) { |  | ||||||
|   long i, x; |  | ||||||
|   x = t->events.p[ev].arg[arg].name; |  | ||||||
|   if (x != -1) { |  | ||||||
|     fprintf(f, "b%`'.*s:", t->slices.p[x].n, t->slices.p[x].p); |  | ||||||
|   } |  | ||||||
|   x = t->events.p[ev].arg[arg].x; |  | ||||||
|   switch (t->events.p[ev].arg[arg].kind) { |  | ||||||
|     case AK_LONG: |  | ||||||
|       fprintf(f, "%ld", x); |  | ||||||
|       break; |  | ||||||
|     case AK_STR: |  | ||||||
|       fprintf(f, "b%`'.*s", t->slices.p[x].n, t->slices.p[x].p); |  | ||||||
|       break; |  | ||||||
|     case AK_INTPAIR: |  | ||||||
|       fprintf(f, "(%d,%d)", x >> 32, x); |  | ||||||
|       break; |  | ||||||
|     case AK_STRLIST: |  | ||||||
|       fprintf(f, "("); |  | ||||||
|       for (i = 0; i < t->strlists.p[x].n; ++i) { |  | ||||||
|         fprintf(f, "b%`'.*s,", t->slices.p[t->strlists.p[x].p[i]].n, |  | ||||||
|                 t->slices.p[t->strlists.p[x].p[i]].p); |  | ||||||
|       } |  | ||||||
|       fprintf(f, ")"); |  | ||||||
|       break; |  | ||||||
|     default: |  | ||||||
|       abort(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void PrintEvent(FILE *f, struct Trace *t, long ev) { |  | ||||||
|   long arg; |  | ||||||
|   fprintf(f, "(%d,%ld,%d,%d,", t->events.p[ev].pid, |  | ||||||
|           t->events.p[ev].sec * 1000000 + t->events.p[ev].us, |  | ||||||
|           t->events.p[ev].elap, t->events.p[ev].kind); |  | ||||||
|   switch (t->events.p[ev].kind) { |  | ||||||
|     case EK_EXIT: |  | ||||||
|     case EK_SIGNAL: |  | ||||||
|     case EK_KILLED: |  | ||||||
|       fprintf(f, "%d", t->events.p[ev].ret); |  | ||||||
|       break; |  | ||||||
|     case EK_CALL: |  | ||||||
|       CHECK_LT(t->events.p[ev].syscall_, ARRAYLEN(kSyscalls)); |  | ||||||
|       fprintf(f, "(b%`'s,%ld,", kSyscalls[t->events.p[ev].syscall_].name, |  | ||||||
|               t->events.p[ev].ret); |  | ||||||
|       fprintf(f, "%c", |  | ||||||
|               t->events.p[ev].arity && t->events.p[ev].arg[0].name != -1 ? '{' |  | ||||||
|                                                                          : '('); |  | ||||||
|       for (arg = 0; arg < t->events.p[ev].arity; ++arg) { |  | ||||||
|         PrintArg(f, t, ev, arg); |  | ||||||
|         fprintf(f, ","); |  | ||||||
|       } |  | ||||||
|       fprintf(f, "%c)", |  | ||||||
|               t->events.p[ev].arity && t->events.p[ev].arg[0].name != -1 ? '}' |  | ||||||
|                                                                          : ')'); |  | ||||||
|       break; |  | ||||||
|     default: |  | ||||||
|       break; |  | ||||||
|   } |  | ||||||
|   fprintf(f, ")"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void AppendArg(char *arg) { |  | ||||||
|   strace_args = realloc(strace_args, ++strace_args_len * sizeof(*strace_args)); |  | ||||||
|   strace_args[strace_args_len - 1] = arg; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static wontreturn void PrintUsage(FILE *f, int rc) { |  | ||||||
|   fprintf(f, "Usage: %s [-o OUT] PROG [ARGS...]\n", program_invocation_name); |  | ||||||
|   exit(rc); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int i; |  | ||||||
|   int ws; |  | ||||||
|   int opt; |  | ||||||
|   int pid; |  | ||||||
|   long ev; |  | ||||||
|   FILE *fin; |  | ||||||
|   FILE *fout; |  | ||||||
|   char *line; |  | ||||||
|   long lineno; |  | ||||||
|   char *strace; |  | ||||||
|   int pipefds[2]; |  | ||||||
|   struct Trace *t; |  | ||||||
|   sigset_t block, mask; |  | ||||||
|   struct sigaction ignore, saveint, savequit; |  | ||||||
| 
 |  | ||||||
|   /*
 |  | ||||||
|    * parse prefix arguments |  | ||||||
|    */ |  | ||||||
|   fout = stderr; |  | ||||||
|   while ((opt = getopt(argc, argv, "?ho:")) != -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case 'o': |  | ||||||
|         fout = fopen(optarg, "w"); |  | ||||||
|         break; |  | ||||||
|       case 'h': |  | ||||||
|       case '?': |  | ||||||
|         PrintUsage(stdout, EXIT_SUCCESS); |  | ||||||
|       default: |  | ||||||
|         PrintUsage(stderr, EX_USAGE); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (optind == argc) { |  | ||||||
|     PrintUsage(stderr, EX_USAGE); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   /*
 |  | ||||||
|    * resolve full paths of dependencies |  | ||||||
|    */ |  | ||||||
|   if ((strace = commandvenv("STRACE", "strace"))) { |  | ||||||
|     strace = strdup(strace); |  | ||||||
|   } else { |  | ||||||
|     fprintf(stderr, "error: please install strace\n"); |  | ||||||
|     exit(1); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   /*
 |  | ||||||
|    * create strace argument list |  | ||||||
|    */ |  | ||||||
|   AppendArg("strace"); |  | ||||||
|   AppendArg("-q");         // don't log attach/detach noise
 |  | ||||||
|   AppendArg("-v");         // don't abbreviate arrays
 |  | ||||||
|   AppendArg("-f");         // follow subprocesses
 |  | ||||||
|   AppendArg("-ttt");       // print unixseconds.micros
 |  | ||||||
|   AppendArg("-X");         // print numbers instead of symbols
 |  | ||||||
|   AppendArg("raw");        //   e.g. 2 vs. O_RDWR
 |  | ||||||
|   AppendArg("-s");         // don't abbreviate data
 |  | ||||||
|   AppendArg("805306368");  //   strace won't let us go higher
 |  | ||||||
|   AppendArg("-e");         // system calls that matter
 |  | ||||||
|   AppendArg( |  | ||||||
|       "open,close,access,pipe,dup,dup2,socket,connect,accept,bind,listen," |  | ||||||
|       "socketpair,fork,vfork,execve,clone,flock,fsync,fdatasync,truncate,chdir," |  | ||||||
|       "rename,mkdir,rmdir,creat,link,unlink,symlink,readlink,chmod,chown,fcntl," |  | ||||||
|       "lchown,mknod,mknodat,statfs,chroot,sync,epoll_create,openat,mkdirat," |  | ||||||
|       "fchownat,unlinkat,renameat,linkat,symlinkat,readlinkat,fchmodat,fchdir," |  | ||||||
|       "faccessat,utimensat,accept4,dup3,pipe2,epoll_create1,signalfd,signalfd4," |  | ||||||
|       "eventfd,eventfd2,timerfd_create,syncfs,renameat2,memfd_create,execveat"); |  | ||||||
|   CHECK_NE(-1, pipe(pipefds)); |  | ||||||
|   AppendArg("-o"); |  | ||||||
|   AppendArg(xasprintf("/dev/fd/%d", pipefds[1])); |  | ||||||
|   for (i = optind; i < argc; ++i) { |  | ||||||
|     AppendArg(argv[i]); |  | ||||||
|   } |  | ||||||
|   AppendArg(NULL); |  | ||||||
| 
 |  | ||||||
|   /*
 |  | ||||||
|    * spawn strace |  | ||||||
|    */ |  | ||||||
|   ignore.sa_flags = 0; |  | ||||||
|   ignore.sa_handler = SIG_IGN; |  | ||||||
|   sigemptyset(&ignore.sa_mask); |  | ||||||
|   sigaction(SIGINT, &ignore, &saveint); |  | ||||||
|   sigaction(SIGQUIT, &ignore, &savequit); |  | ||||||
|   sigfillset(&block); |  | ||||||
|   sigprocmask(SIG_BLOCK, &block, &mask); |  | ||||||
|   CHECK_NE(-1, (pid = vfork())); |  | ||||||
|   if (!pid) { |  | ||||||
|     close(pipefds[0]); |  | ||||||
|     sigaction(SIGINT, &saveint, NULL); |  | ||||||
|     sigaction(SIGQUIT, &savequit, NULL); |  | ||||||
|     sigprocmask(SIG_SETMASK, &mask, NULL); |  | ||||||
|     execv(strace, strace_args); |  | ||||||
|     _exit(127); |  | ||||||
|   } |  | ||||||
|   close(pipefds[1]); |  | ||||||
|   sigaddset(&mask, SIGCHLD); |  | ||||||
|   sigprocmask(SIG_SETMASK, &mask, NULL); |  | ||||||
| 
 |  | ||||||
|   /*
 |  | ||||||
|    * read output of strace until eof |  | ||||||
|    */ |  | ||||||
|   fin = fdopen(pipefds[0], "r"); |  | ||||||
|   t = NewTrace(); |  | ||||||
|   for (ev = 0, lineno = 1; !interrupted && (line = xgetline(fin)); ++lineno) { |  | ||||||
|     _chomp(line); |  | ||||||
|     Parse(t, line, lineno); |  | ||||||
|     free(line); |  | ||||||
|     for (; ev < t->events.n && !t->events.p[ev].is_interrupted; ++ev) { |  | ||||||
|       PrintEvent(fout, t, ev); |  | ||||||
|       fprintf(fout, "\n"); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   FreeTrace(t); |  | ||||||
|   CHECK_NE(-1, fclose(fout)); |  | ||||||
| 
 |  | ||||||
|   /*
 |  | ||||||
|    * wait for strace to exit |  | ||||||
|    */ |  | ||||||
|   while (waitpid(pid, &ws, 0) == -1) { |  | ||||||
|     CHECK_EQ(EINTR, errno); |  | ||||||
|   } |  | ||||||
|   CHECK_NE(-1, fclose(fin)); |  | ||||||
| 
 |  | ||||||
|   /*
 |  | ||||||
|    * propagate exit |  | ||||||
|    */ |  | ||||||
|   if (WIFEXITED(ws)) { |  | ||||||
|     return WEXITSTATUS(ws); |  | ||||||
|   } else { |  | ||||||
|     return 128 + WTERMSIG(ws); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -17,21 +17,27 @@ | ||||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||||
| #include "libc/calls/calls.h" | #include "libc/calls/calls.h" | ||||||
|  | #include "libc/runtime/runtime.h" | ||||||
| #include "libc/stdio/stdio.h" | #include "libc/stdio/stdio.h" | ||||||
|  | #include "libc/str/str.h" | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @fileoverview Tool for printing current directory. |  * @fileoverview Tool for printing current directory. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| char path[PATH_MAX]; |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   char *p; |   char path[PATH_MAX + 2]; | ||||||
|   if ((p = getcwd(path, sizeof(path)))) { | 
 | ||||||
|     fputs(p, stdout); |   if (!getcwd(path, PATH_MAX)) { | ||||||
|     fputc('\n', stdout); |     perror(argv[0]); | ||||||
|     return 0; |     exit(1); | ||||||
|   } else { |  | ||||||
|     return 1; |  | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   strcat(path, "\n"); | ||||||
|  |   if (write(1, path, strlen(path)) == -1) { | ||||||
|  |     perror("write"); | ||||||
|  |     exit(1); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,134 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/assert.h" |  | ||||||
| #include "libc/calls/calls.h" |  | ||||||
| #include "libc/calls/struct/dirent.h" |  | ||||||
| #include "libc/calls/struct/stat.h" |  | ||||||
| #include "libc/fmt/fmt.h" |  | ||||||
| #include "libc/intrin/safemacros.internal.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/mem/alg.h" |  | ||||||
| #include "libc/mem/gc.internal.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/dt.h" |  | ||||||
| #include "libc/sysv/consts/map.h" |  | ||||||
| #include "libc/sysv/consts/o.h" |  | ||||||
| #include "libc/sysv/consts/prot.h" |  | ||||||
| #include "libc/x/x.h" |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * @fileoverview Pretty fast substring refactor tool. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| static const char kBefore[] = "\
 |  | ||||||
| │ Copyright 2020 Justine Alexandra Roberts Tunney                              │\n\ |  | ||||||
| │                                                                              │\n\ |  | ||||||
| │ This program is free software; you can redistribute it and/or modify         │\n\ |  | ||||||
| │ it under the terms of the GNU General Public License as published by         │\n\ |  | ||||||
| │ the Free Software Foundation; version 2 of the License.                      │\n\ |  | ||||||
| │                                                                              │\n\ |  | ||||||
| │ This program is distributed in the hope that it will be useful, but          │\n\ |  | ||||||
| │ WITHOUT ANY WARRANTY; without even the implied warranty of                   │\n\ |  | ||||||
| │ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU             │\n\ |  | ||||||
| │ General Public License for more details.                                     │\n\ |  | ||||||
| │                                                                              │\n\ |  | ||||||
| │ You should have received a copy of the GNU General Public License            │\n\ |  | ||||||
| │ along with this program; if not, write to the Free Software                  │\n\ |  | ||||||
| │ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA                │\n\ |  | ||||||
| │ 02110-1301 USA                                                               │\n\ |  | ||||||
| "; |  | ||||||
| const char kAfter[] = "\
 |  | ||||||
| │ Copyright 2020 Justine Alexandra Roberts Tunney                              │\n\ |  | ||||||
| │                                                                              │\n\ |  | ||||||
| │ Permission to use, copy, modify, and/or distribute this software for         │\n\ |  | ||||||
| │ any purpose with or without fee is hereby granted, provided that the         │\n\ |  | ||||||
| │ above copyright notice and this permission notice appear in all copies.      │\n\ |  | ||||||
| │                                                                              │\n\ |  | ||||||
| │ THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL                │\n\
 |  | ||||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │\n\ |  | ||||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │\n\ |  | ||||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │\n\ |  | ||||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │\n\ |  | ||||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │\n\ |  | ||||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │\n\ |  | ||||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │\n\ |  | ||||||
| "; |  | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
| static const char kBefore[] = "\
 |  | ||||||
| /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│";
 |  | ||||||
| const char kAfter[] = "\
 |  | ||||||
| /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│";
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| void RefactorFile(const char *path) { |  | ||||||
|   int fd; |  | ||||||
|   struct stat st; |  | ||||||
|   size_t len, partlen, len1, len2; |  | ||||||
|   char *mem, *spot = NULL, *part1, *part2; |  | ||||||
|   CHECK_NE(-1, (fd = open(path, O_RDONLY))); |  | ||||||
|   CHECK_NE(-1, fstat(fd, &st)); |  | ||||||
|   len2 = 0; |  | ||||||
|   if ((len = st.st_size)) { |  | ||||||
|     CHECK_NE(MAP_FAILED, |  | ||||||
|              (mem = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0))); |  | ||||||
|     partlen = sizeof(kBefore) - 1; |  | ||||||
|     if ((spot = memmem(mem, len, kBefore, partlen))) { |  | ||||||
|       part1 = gc(xmalloc((len1 = spot - mem))); |  | ||||||
|       part2 = gc(xmalloc((len2 = len - partlen - (spot - mem)))); |  | ||||||
|       memcpy(part1, mem, len1); |  | ||||||
|       memcpy(part2, spot + partlen, len2); |  | ||||||
|     } |  | ||||||
|     CHECK_NE(-1, munmap(mem, len)); |  | ||||||
|   } |  | ||||||
|   CHECK_NE(-1, close(fd)); |  | ||||||
|   if (spot) { |  | ||||||
|     fprintf(stderr, "found! %s\n", path); |  | ||||||
|     CHECK_NE(-1, (fd = open(path, O_RDWR | O_TRUNC))); |  | ||||||
|     CHECK_EQ(len1, write(fd, part1, len1)); |  | ||||||
|     CHECK_EQ(sizeof(kAfter) - 1, write(fd, kAfter, sizeof(kAfter) - 1)); |  | ||||||
|     CHECK_EQ(len2, write(fd, part2, len2)); |  | ||||||
|     CHECK_NE(-1, close(fd)); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void RefactorDir(const char *dpath) { |  | ||||||
|   DIR *dir; |  | ||||||
|   struct dirent *ent; |  | ||||||
|   char *path = gc(xmalloc(4096)); |  | ||||||
|   CHECK_NOTNULL(dir = opendir(firstnonnull(dpath, "."))); |  | ||||||
|   while ((ent = readdir(dir))) { |  | ||||||
|     if (_startswith(ent->d_name, ".")) continue; |  | ||||||
|     if (strcmp(ent->d_name, "o") == 0) continue; |  | ||||||
|     snprintf(path, 4096, "%s%s%s", dpath ? dpath : "", dpath ? "/" : "", |  | ||||||
|              ent->d_name); |  | ||||||
|     if (isdirectory(path)) { |  | ||||||
|       RefactorDir(path); |  | ||||||
|     } else if (isregularfile(path)) { |  | ||||||
|       RefactorFile(path); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   CHECK_NE(-1, closedir(dir)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   RefactorDir(NULL); |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
							
								
								
									
										251
									
								
								tool/build/rle.c
									
										
									
									
									
								
							
							
						
						
									
										251
									
								
								tool/build/rle.c
									
										
									
									
									
								
							|  | @ -1,251 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/calls/calls.h" |  | ||||||
| #include "libc/dce.h" |  | ||||||
| #include "libc/errno.h" |  | ||||||
| #include "libc/fmt/fmt.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/macros.internal.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/exit.h" |  | ||||||
| #include "libc/sysv/errfuns.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| 
 |  | ||||||
| #define USAGE1 \ |  | ||||||
|   "NAME\n\
 |  | ||||||
| \n\ |  | ||||||
|   rle - Run Length Encoder\n\ |  | ||||||
| \n\ |  | ||||||
| SYNOPSIS\n\ |  | ||||||
| \n\ |  | ||||||
|   " |  | ||||||
| 
 |  | ||||||
| #define USAGE2 \ |  | ||||||
|   " [FLAGS] [FILE...]\n\
 |  | ||||||
| \n\ |  | ||||||
| DESCRIPTION\n\ |  | ||||||
| \n\ |  | ||||||
|   This is a primitive compression algorithm. Its advantage is that\n\ |  | ||||||
|   the concomitant rldecode() library is seventeen bytes, and works\n\ |  | ||||||
|   on IA-16, IA-32, and NexGen32e without needing to be recompiled.\n\ |  | ||||||
| \n\ |  | ||||||
|   This CLI is consistent with gzip, bzip2, lzma, etc.\n\ |  | ||||||
| \n\ |  | ||||||
| FLAGS\n\ |  | ||||||
| \n\ |  | ||||||
|   -1 .. -9   ignored\n\ |  | ||||||
|   -a         ignored\n\ |  | ||||||
|   -c         send to stdout\n\ |  | ||||||
|   -d         decompress\n\ |  | ||||||
|   -f         ignored\n\ |  | ||||||
|   -t         test integrity\n\ |  | ||||||
|   -S SUFFIX  overrides .rle extension\n\ |  | ||||||
|   -h         shows this information\n" |  | ||||||
| 
 |  | ||||||
| FILE *fin_, *fout_; |  | ||||||
| bool decompress_, test_; |  | ||||||
| const char *suffix_, *hint_; |  | ||||||
| 
 |  | ||||||
| void StartErrorMessage(void) { |  | ||||||
|   fputs("error: ", stderr); |  | ||||||
|   fputs(hint_, stderr); |  | ||||||
|   fputs(": ", stderr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void PrintIoErrorMessage(void) { |  | ||||||
|   int err; |  | ||||||
|   err = errno; |  | ||||||
|   StartErrorMessage(); |  | ||||||
|   fputs(strerror(err), stderr); |  | ||||||
|   fputc('\n', stderr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void PrintUsage(int rc, FILE *f) { |  | ||||||
|   fputs(USAGE1, f); |  | ||||||
|   fputs(program_invocation_name, f); |  | ||||||
|   fputs(USAGE2, f); |  | ||||||
|   exit(rc); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GetOpts(int argc, char *argv[]) { |  | ||||||
|   int opt; |  | ||||||
|   fin_ = stdin; |  | ||||||
|   suffix_ = ".rle"; |  | ||||||
|   while ((opt = getopt(argc, argv, "123456789S:acdfho:t")) != -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case '1': |  | ||||||
|       case '2': |  | ||||||
|       case '3': |  | ||||||
|       case '4': |  | ||||||
|       case '5': |  | ||||||
|       case '6': |  | ||||||
|       case '7': |  | ||||||
|       case '8': |  | ||||||
|       case '9': |  | ||||||
|       case 'a': |  | ||||||
|       case 'f': |  | ||||||
|         break; |  | ||||||
|       case 'c': |  | ||||||
|         fout_ = stdout; |  | ||||||
|         break; |  | ||||||
|       case 'd': |  | ||||||
|         decompress_ = true; |  | ||||||
|         break; |  | ||||||
|       case 't': |  | ||||||
|         test_ = true; |  | ||||||
|         break; |  | ||||||
|       case 'o': |  | ||||||
|         fclose(fout_); |  | ||||||
|         if (!(fout_ = fopen((hint_ = optarg), "w"))) { |  | ||||||
|           PrintIoErrorMessage(); |  | ||||||
|           exit(1); |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|       case 'S': |  | ||||||
|         suffix_ = optarg; |  | ||||||
|         break; |  | ||||||
|       case 'h': |  | ||||||
|       case '?': |  | ||||||
|         PrintUsage(EXIT_SUCCESS, stdout); |  | ||||||
|       default: |  | ||||||
|         PrintUsage(EX_USAGE, stderr); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int RunLengthEncode1(void) { |  | ||||||
|   int byte1, byte2, runlength; |  | ||||||
|   byte2 = -1; |  | ||||||
|   runlength = 0; |  | ||||||
|   if ((byte1 = fgetc(fin_)) == -1) return -1; |  | ||||||
|   do { |  | ||||||
|     while (++runlength < 255) { |  | ||||||
|       if ((byte2 = fgetc(fin_)) != byte1) break; |  | ||||||
|     } |  | ||||||
|     if (fputc(runlength, fout_) == -1 || fputc(byte1, fout_) == -1) { |  | ||||||
|       return -1; |  | ||||||
|     } |  | ||||||
|     runlength = 0; |  | ||||||
|   } while ((byte1 = byte2) != -1); |  | ||||||
|   return feof(fin_) ? 0 : -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int RunLengthEncode2(void) { |  | ||||||
|   return fputc(0, fout_) | fputc(0, fout_); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int EmitRun(unsigned char count, unsigned char byte) { |  | ||||||
|   do { |  | ||||||
|     if (fputc(byte, fout_) == -1) return -1; |  | ||||||
|   } while (--count); |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int RunLengthDecode(void) { |  | ||||||
|   int byte1, byte2; |  | ||||||
|   if ((byte1 = fgetc(fin_)) == -1) return einval(); |  | ||||||
|   if ((byte2 = fgetc(fin_)) == -1) return einval(); |  | ||||||
|   while (byte1) { |  | ||||||
|     if (!test_ && EmitRun(byte1, byte2) == -1) return -1; |  | ||||||
|     if ((byte1 = fgetc(fin_)) == -1) break; |  | ||||||
|     if ((byte2 = fgetc(fin_)) == -1) return einval(); |  | ||||||
|   } |  | ||||||
|   if (byte1 != 0 || byte2 != 0) return einval(); |  | ||||||
|   fgetc(fin_); |  | ||||||
|   return feof(fin_) ? 0 : -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int RunLengthCode(void) { |  | ||||||
|   if (test_ || decompress_) { |  | ||||||
|     return RunLengthDecode(); |  | ||||||
|   } else { |  | ||||||
|     return RunLengthEncode1(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int Run(char **paths, size_t count) { |  | ||||||
|   int rc; |  | ||||||
|   char *p; |  | ||||||
|   size_t i, suffixlen; |  | ||||||
|   const char pathbuf[PATH_MAX]; |  | ||||||
|   if (!count) { |  | ||||||
|     hint_ = "/dev/stdin"; |  | ||||||
|     if (!fout_) fout_ = stdout; |  | ||||||
|     rc = RunLengthCode(); |  | ||||||
|     rc |= fclose(fin_); |  | ||||||
|     fin_ = 0; |  | ||||||
|   } else { |  | ||||||
|     rc = fclose(fin_); |  | ||||||
|     fin_ = 0; |  | ||||||
|     for (i = 0; i < count && rc != -1; ++i) { |  | ||||||
|       rc = -1; |  | ||||||
|       if ((fin_ = fopen((hint_ = paths[i]), "r"))) { |  | ||||||
|         if (test_ || fout_) { |  | ||||||
|           rc = RunLengthCode(); |  | ||||||
|         } else { |  | ||||||
|           suffixlen = strlen(suffix_); |  | ||||||
|           if (!IsTrustworthy() && |  | ||||||
|               strlen(paths[i]) + suffixlen >= ARRAYLEN(pathbuf)) { |  | ||||||
|             return eoverflow(); |  | ||||||
|           } |  | ||||||
|           p = stpcpy(pathbuf, paths[i]); |  | ||||||
|           if (!decompress_) { |  | ||||||
|             strcpy(p, suffix_); |  | ||||||
|           } else if (p - pathbuf > suffixlen && |  | ||||||
|                      memcmp(p - suffixlen, suffix_, suffixlen) == 0) { |  | ||||||
|             p[-suffixlen] = '\0'; |  | ||||||
|           } else { |  | ||||||
|             return enotsup(); |  | ||||||
|           } |  | ||||||
|           if ((fout_ = fopen((hint_ = pathbuf), "w"))) { |  | ||||||
|             rc = RunLengthCode(); |  | ||||||
|             if (rc != -1 && !decompress_) { |  | ||||||
|               rc = RunLengthEncode2(); |  | ||||||
|             } |  | ||||||
|             if ((rc |= fclose(fout_)) != -1) { |  | ||||||
|               unlink(paths[i]); |  | ||||||
|             } |  | ||||||
|             fout_ = 0; |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|         rc |= fclose(fin_); |  | ||||||
|         fin_ = 0; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (rc != -1 && fout_) { |  | ||||||
|     rc = RunLengthEncode2(); |  | ||||||
|     rc |= fclose(fout_); |  | ||||||
|     fout_ = 0; |  | ||||||
|   } |  | ||||||
|   return rc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   GetOpts(argc, argv); |  | ||||||
|   if (Run(argv + optind, argc - optind) != -1) { |  | ||||||
|     return EXIT_SUCCESS; |  | ||||||
|   } else { |  | ||||||
|     PrintIoErrorMessage(); |  | ||||||
|     return EXIT_FAILURE; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -22,8 +22,6 @@ | ||||||
| #include "libc/runtime/runtime.h" | #include "libc/runtime/runtime.h" | ||||||
| #include "libc/stdio/stdio.h" | #include "libc/stdio/stdio.h" | ||||||
| #include "libc/str/str.h" | #include "libc/str/str.h" | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/exit.h" |  | ||||||
| #include "libc/sysv/consts/ok.h" | #include "libc/sysv/consts/ok.h" | ||||||
| #include "third_party/getopt/getopt.internal.h" | #include "third_party/getopt/getopt.internal.h" | ||||||
| 
 | 
 | ||||||
|  | @ -36,63 +34,53 @@ SYNOPSIS\n\ | ||||||
| \n\ | \n\ | ||||||
| FLAGS\n\ | FLAGS\n\ | ||||||
| \n\ | \n\ | ||||||
|   -?\n\ |  | ||||||
|   -h      help\n\ |   -h      help\n\ | ||||||
|   -f      force\n\ |   -f      force\n\ | ||||||
| \n" | \n" | ||||||
| 
 | 
 | ||||||
| bool force; | static bool force; | ||||||
| const char *prog; | static const char *prog; | ||||||
| 
 | 
 | ||||||
| wontreturn void PrintUsage(int rc, FILE *f) { | static wontreturn void PrintUsage(int rc, int fd) { | ||||||
|   fputs("usage: ", f); |   tinyprint(fd, "USAGE\n\n  ", prog, USAGE, NULL); | ||||||
|   fputs(prog, f); |  | ||||||
|   fputs(USAGE, f); |  | ||||||
|   exit(rc); |   exit(rc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetOpts(int argc, char *argv[]) { | static void GetOpts(int argc, char *argv[]) { | ||||||
|   int opt; |   int opt; | ||||||
|   while ((opt = getopt(argc, argv, "?hf")) != -1) { |   while ((opt = getopt(argc, argv, "hf")) != -1) { | ||||||
|     switch (opt) { |     switch (opt) { | ||||||
|       case 'f': |       case 'f': | ||||||
|         force = true; |         force = true; | ||||||
|         break; |         break; | ||||||
|       case 'h': |       case 'h': | ||||||
|       case '?': |         PrintUsage(0, 1); | ||||||
|         PrintUsage(EXIT_SUCCESS, stdout); |  | ||||||
|       default: |       default: | ||||||
|         PrintUsage(EX_USAGE, stderr); |         PrintUsage(1, 2); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Remove(const char *path) { | static void Remove(const char *path) { | ||||||
|   const char *s; |   if (!force && access(path, W_OK) == -1) { | ||||||
|   if (!force && access(path, W_OK) == -1) goto OnFail; |     perror(path); | ||||||
|   if (unlink(path) == -1) goto OnFail; |     exit(1); | ||||||
|   return; |   } | ||||||
| OnFail: |   if (unlink(path) == -1) { | ||||||
|   if (force && errno == ENOENT) return; |     if (force && errno == ENOENT) return; | ||||||
|   s = _strerdoc(errno); |     perror(path); | ||||||
|   fputs(prog, stderr); |     exit(1); | ||||||
|   fputs(": cannot remove '", stderr); |   } | ||||||
|   fputs(path, stderr); |  | ||||||
|   fputs("': ", stderr); |  | ||||||
|   fputs(s, stderr); |  | ||||||
|   fputs("\n", stderr); |  | ||||||
|   exit(1); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   int i; |   int i; | ||||||
|   prog = argc > 0 ? argv[0] : "rm.com"; | 
 | ||||||
|  |   prog = argv[0]; | ||||||
|  |   if (!prog) prog = "rm"; | ||||||
| 
 | 
 | ||||||
|   if (argc < 2) { |   if (argc < 2) { | ||||||
|     fputs(prog, stderr); |     tinyprint(2, prog, ": missing operand\n", NULL); | ||||||
|     fputs(": missing operand\n" |  | ||||||
|           "Try 'rm -h' for more information.\n", |  | ||||||
|           stderr); |  | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,17 +28,15 @@ | ||||||
| #include "third_party/getopt/getopt.internal.h" | #include "third_party/getopt/getopt.internal.h" | ||||||
| #include "third_party/mbedtls/sha256.h" | #include "third_party/mbedtls/sha256.h" | ||||||
| 
 | 
 | ||||||
| #define PROG "sha256sum" |  | ||||||
| #define USAGE \ | #define USAGE \ | ||||||
|   "\
 |   "[-?hbctw] [PATH...]\n\
 | ||||||
| Usage: " PROG " [-?hbctw] [PATH...]\n\ |  | ||||||
|   -h          help\n\ |   -h          help\n\ | ||||||
|   -c          check mode\n\ |   -c          check mode\n\ | ||||||
|   -b          binary mode\n\ |   -b          binary mode\n\ | ||||||
|   -t          textual mode\n\ |   -t          textual mode\n\ | ||||||
|   -w          warning mode\n\ |   -w          warning mode\n\ | ||||||
| \n\ | \n\ | ||||||
| cosmopolitan " PROG " v1.0\n\ | cosmopolitan sha256sum v1.1\n\ | ||||||
| copyright 2022 justine alexandra roberts tunney\n\ | copyright 2022 justine alexandra roberts tunney\n\ | ||||||
| notice licenses are embedded in the binary\n\ | notice licenses are embedded in the binary\n\ | ||||||
| https://twitter.com/justinetunney\n\ | https://twitter.com/justinetunney\n\ | ||||||
|  | @ -56,11 +54,17 @@ static bool g_warn; | ||||||
| static char g_mode; | static char g_mode; | ||||||
| static bool g_check; | static bool g_check; | ||||||
| static int g_mismatches; | static int g_mismatches; | ||||||
|  | static const char *prog; | ||||||
|  | 
 | ||||||
|  | static wontreturn void PrintUsage(int rc, int fd) { | ||||||
|  |   tinyprint(fd, "Usage: ", prog, USAGE, NULL); | ||||||
|  |   exit(rc); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| static void GetOpts(int argc, char *argv[]) { | static void GetOpts(int argc, char *argv[]) { | ||||||
|   int opt; |   int opt; | ||||||
|   g_mode = ' '; |   g_mode = ' '; | ||||||
|   while ((opt = getopt(argc, argv, "?hbctw")) != -1) { |   while ((opt = getopt(argc, argv, "hbctw")) != -1) { | ||||||
|     switch (opt) { |     switch (opt) { | ||||||
|       case 'w': |       case 'w': | ||||||
|         g_warn = true; |         g_warn = true; | ||||||
|  | @ -75,28 +79,13 @@ static void GetOpts(int argc, char *argv[]) { | ||||||
|         g_mode = '*'; |         g_mode = '*'; | ||||||
|         break; |         break; | ||||||
|       case 'h': |       case 'h': | ||||||
|       case '?': |         PrintUsage(0, 1); | ||||||
|         write(1, USAGE, sizeof(USAGE) - 1); |  | ||||||
|         exit(0); |  | ||||||
|       default: |       default: | ||||||
|         write(2, USAGE, sizeof(USAGE) - 1); |         PrintUsage(1, 2); | ||||||
|         exit(64); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static ssize_t Write(int fd, const char *s, ...) { |  | ||||||
|   va_list va; |  | ||||||
|   char buf[512]; |  | ||||||
|   buf[0] = 0; |  | ||||||
|   va_start(va, s); |  | ||||||
|   do { |  | ||||||
|     strlcat(buf, s, sizeof(buf)); |  | ||||||
|   } while ((s = va_arg(va, const char *))); |  | ||||||
|   va_end(va); |  | ||||||
|   return write(fd, buf, strlen(buf)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool IsModeCharacter(char c) { | static bool IsModeCharacter(char c) { | ||||||
|   switch (c) { |   switch (c) { | ||||||
|     case ' ': |     case ' ': | ||||||
|  | @ -117,7 +106,7 @@ static bool IsSupportedPath(const char *path) { | ||||||
|       case '\r': |       case '\r': | ||||||
|       case '\n': |       case '\n': | ||||||
|       case '\\': |       case '\\': | ||||||
|         Write(2, PROG, ": ", path, ": unsupported path\n", NULL); |         tinyprint(2, prog, ": ", path, ": unsupported path\n", NULL); | ||||||
|         return false; |         return false; | ||||||
|       default: |       default: | ||||||
|         break; |         break; | ||||||
|  | @ -135,7 +124,7 @@ static bool GetDigest(const char *path, FILE *f, unsigned char digest[32]) { | ||||||
|     _unassert(!mbedtls_sha256_update_ret(&ctx, buf, got)); |     _unassert(!mbedtls_sha256_update_ret(&ctx, buf, got)); | ||||||
|   } |   } | ||||||
|   if (ferror(f)) { |   if (ferror(f)) { | ||||||
|     Write(2, PROG, ": ", path, ": ", _strerdoc(errno), "\n", NULL); |     tinyprint(2, prog, ": ", path, ": ", strerror(errno), "\n", NULL); | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|   _unassert(!mbedtls_sha256_finish_ret(&ctx, digest)); |   _unassert(!mbedtls_sha256_finish_ret(&ctx, digest)); | ||||||
|  | @ -150,7 +139,7 @@ static bool ProduceDigest(const char *path, FILE *f) { | ||||||
|   if (!IsSupportedPath(path)) return false; |   if (!IsSupportedPath(path)) return false; | ||||||
|   if (!GetDigest(path, f, digest)) return false; |   if (!GetDigest(path, f, digest)) return false; | ||||||
|   hexpcpy(hexdigest, digest, 32); |   hexpcpy(hexdigest, digest, 32); | ||||||
|   Write(1, hexdigest, " ", mode, path, "\n", NULL); |   tinyprint(1, hexdigest, " ", mode, path, "\n", NULL); | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -182,13 +171,13 @@ static bool CheckDigests(const char *path, FILE *f) { | ||||||
|           ++g_mismatches; |           ++g_mismatches; | ||||||
|           k = false; |           k = false; | ||||||
|         } |         } | ||||||
|         Write(1, path2, ": ", status, "\n", NULL); |         tinyprint(1, path2, ": ", status, "\n", NULL); | ||||||
|       } else { |       } else { | ||||||
|         k = false; |         k = false; | ||||||
|       } |       } | ||||||
|       fclose(f2); |       fclose(f2); | ||||||
|     } else { |     } else { | ||||||
|       Write(2, PROG, ": ", path2, ": ", _strerdoc(errno), "\n", NULL); |       tinyprint(2, prog, ": ", path2, ": ", strerror(errno), "\n", NULL); | ||||||
|       k = false; |       k = false; | ||||||
|     } |     } | ||||||
|     continue; |     continue; | ||||||
|  | @ -196,12 +185,12 @@ static bool CheckDigests(const char *path, FILE *f) { | ||||||
|     if (g_warn) { |     if (g_warn) { | ||||||
|       char linestr[12]; |       char linestr[12]; | ||||||
|       FormatInt32(linestr, line + 1); |       FormatInt32(linestr, line + 1); | ||||||
|       Write(2, PROG, ": ", path, ":", linestr, ": ", |       tinyprint(2, prog, ": ", path, ":", linestr, ": ", | ||||||
|             "improperly formatted checksum line", "\n", NULL); |                 "improperly formatted checksum line", "\n", NULL); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (ferror(f)) { |   if (ferror(f)) { | ||||||
|     Write(2, PROG, ": ", path, ": ", _strerdoc(errno), "\n", NULL); |     tinyprint(2, prog, ": ", path, ": ", strerror(errno), "\n", NULL); | ||||||
|     k = false; |     k = false; | ||||||
|   } |   } | ||||||
|   return k; |   return k; | ||||||
|  | @ -219,6 +208,8 @@ int main(int argc, char *argv[]) { | ||||||
|   int i; |   int i; | ||||||
|   FILE *f; |   FILE *f; | ||||||
|   bool k = true; |   bool k = true; | ||||||
|  |   prog = argv[0]; | ||||||
|  |   if (!prog) prog = "sha256sum"; | ||||||
|   GetOpts(argc, argv); |   GetOpts(argc, argv); | ||||||
|   if (optind == argc) { |   if (optind == argc) { | ||||||
|     f = stdin; |     f = stdin; | ||||||
|  | @ -229,7 +220,7 @@ int main(int argc, char *argv[]) { | ||||||
|         k &= Process(argv[i], f); |         k &= Process(argv[i], f); | ||||||
|         fclose(f); |         fclose(f); | ||||||
|       } else { |       } else { | ||||||
|         Write(2, PROG, ": ", argv[i], ": ", _strerdoc(errno), "\n", NULL); |         tinyprint(2, prog, ": ", argv[i], ": ", strerror(errno), "\n", NULL); | ||||||
|         k = false; |         k = false; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  | @ -237,8 +228,8 @@ int main(int argc, char *argv[]) { | ||||||
|   if (g_mismatches) { |   if (g_mismatches) { | ||||||
|     char ibuf[12]; |     char ibuf[12]; | ||||||
|     FormatInt32(ibuf, g_mismatches); |     FormatInt32(ibuf, g_mismatches); | ||||||
|     Write(2, PROG, ": WARNING: ", ibuf, " computed checksum did NOT match\n", |     tinyprint(2, prog, ": WARNING: ", ibuf, | ||||||
|           NULL); |               " computed checksum did NOT match\n", NULL); | ||||||
|   } |   } | ||||||
|   return !k; |   return !k; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -17,31 +17,31 @@ | ||||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||||
| #include "libc/calls/calls.h" | #include "libc/calls/calls.h" | ||||||
| #include "libc/errno.h" |  | ||||||
| #include "libc/fmt/magnumstrs.internal.h" |  | ||||||
| #include "libc/runtime/runtime.h" | #include "libc/runtime/runtime.h" | ||||||
| #include "libc/stdio/stdio.h" | #include "libc/stdio/stdio.h" | ||||||
| #include "libc/str/str.h" |  | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @fileoverview Command for updating timestamps on files. |  * @fileoverview file timestamp update command | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   int i; |   int i; | ||||||
|   const char *s, *prog; |   const char *prog; | ||||||
|   prog = argc > 0 ? argv[0] : "touch.com"; | 
 | ||||||
|  |   prog = argv[0]; | ||||||
|  |   if (!prog) prog = "touch"; | ||||||
|  | 
 | ||||||
|  |   if (argc < 2) { | ||||||
|  |     tinyprint(2, prog, ": missing operand\n", NULL); | ||||||
|  |     exit(1); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   for (i = 1; i < argc; ++i) { |   for (i = 1; i < argc; ++i) { | ||||||
|     if (touch(argv[i], 0666) == -1) { |     if (touch(argv[i], 0666) == -1) { | ||||||
|       s = _strerdoc(errno); |       perror(argv[i]); | ||||||
|       fputs(prog, stderr); |  | ||||||
|       fputs(": cannot touch '", stderr); |  | ||||||
|       fputs(argv[i], stderr); |  | ||||||
|       fputs("': ", stderr); |  | ||||||
|       fputs(s, stderr); |  | ||||||
|       fputs("\n", stderr); |  | ||||||
|       exit(1); |       exit(1); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -74,7 +74,8 @@ int Visit(const char *fpath, const struct stat *sb, int tflag, | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|   if (!IsLinux()) return 0; |   if (!IsLinux()) return 0; | ||||||
|   prog = argc > 0 ? argv[0] : "unbundle.com"; |   prog = argv[0]; | ||||||
|  |   if (!prog) prog = "unbundle"; | ||||||
|   if (IsDirectory("o/third_party/gcc")) return 0; |   if (IsDirectory("o/third_party/gcc")) return 0; | ||||||
|   makedirs("o/third_party", 0755); |   makedirs("o/third_party", 0755); | ||||||
|   FormatInt32(stpcpy(tmpdir, "o/third_party/gcc."), getpid()); |   FormatInt32(stpcpy(tmpdir, "o/third_party/gcc."), getpid()); | ||||||
|  |  | ||||||
|  | @ -1,330 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2022 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 "libc/assert.h" |  | ||||||
| #include "libc/calls/calls.h" |  | ||||||
| #include "libc/fmt/conv.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/math.h" |  | ||||||
| #include "libc/mem/gc.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/str/tab.internal.h" |  | ||||||
| #include "libc/x/xasprintf.h" |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * @fileoverview Tool for generating rldecode'd character sets, e.g. |  | ||||||
|  * |  | ||||||
|  *     # generate http token table |  | ||||||
|  *     o//tool/build/xlat.com -TiC ' ()<>@,;:\"/[]?={}' -i
 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| int dig; |  | ||||||
| int xlat[256]; |  | ||||||
| bool identity; |  | ||||||
| const char *symbol; |  | ||||||
| 
 |  | ||||||
| static int Bing(int c) { |  | ||||||
|   if (!c) return L'∅'; |  | ||||||
|   if (c == ' ') return L'␠'; |  | ||||||
|   if (c == '$') return L'§'; |  | ||||||
|   if (c == '\\') return L'⭝'; |  | ||||||
|   return kCp437[c & 255]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void Fill(int f(int)) { |  | ||||||
|   int i; |  | ||||||
|   for (i = 0; i < 256; ++i) { |  | ||||||
|     if (f(i)) { |  | ||||||
|       xlat[i] = identity ? i : 1; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void Invert(void) { |  | ||||||
|   int i; |  | ||||||
|   for (i = 0; i < 256; ++i) { |  | ||||||
|     xlat[i] = !xlat[i]; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void Negate(void) { |  | ||||||
|   int i; |  | ||||||
|   for (i = 0; i < 256; ++i) { |  | ||||||
|     xlat[i] = ~xlat[i] & 255; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void Negative(void) { |  | ||||||
|   int i; |  | ||||||
|   for (i = 0; i < 256; ++i) { |  | ||||||
|     xlat[i] = -xlat[i] & 255; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool ArgNeedsShellQuotes(const char *s) { |  | ||||||
|   if (*s) { |  | ||||||
|     for (;;) { |  | ||||||
|       switch (*s++ & 255) { |  | ||||||
|         case 0: |  | ||||||
|           return false; |  | ||||||
|         case '-': |  | ||||||
|         case '.': |  | ||||||
|         case '/': |  | ||||||
|         case '_': |  | ||||||
|         case '=': |  | ||||||
|         case ':': |  | ||||||
|         case '0' ... '9': |  | ||||||
|         case 'A' ... 'Z': |  | ||||||
|         case 'a' ... 'z': |  | ||||||
|           break; |  | ||||||
|         default: |  | ||||||
|           return true; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } else { |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static char *AddShellQuotes(const char *s) { |  | ||||||
|   char *p, *q; |  | ||||||
|   size_t i, j, n; |  | ||||||
|   n = strlen(s); |  | ||||||
|   p = malloc(1 + n * 5 + 1 + 1); |  | ||||||
|   j = 0; |  | ||||||
|   p[j++] = '\''; |  | ||||||
|   for (i = 0; i < n; ++i) { |  | ||||||
|     if (s[i] != '\'') { |  | ||||||
|       p[j++] = s[i]; |  | ||||||
|     } else { |  | ||||||
|       p[j + 0] = '\''; |  | ||||||
|       p[j + 1] = '"'; |  | ||||||
|       p[j + 2] = '\''; |  | ||||||
|       p[j + 3] = '"'; |  | ||||||
|       p[j + 4] = '\''; |  | ||||||
|       j += 5; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   p[j++] = '\''; |  | ||||||
|   p[j] = 0; |  | ||||||
|   if ((q = realloc(p, j + 1))) p = q; |  | ||||||
|   return p; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static const char *GetArg(char *argv[], int i, int *k) { |  | ||||||
|   if (argv[*k][i + 1]) { |  | ||||||
|     return argv[*k] + i + 1; |  | ||||||
|   } else { |  | ||||||
|     return argv[++*k]; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   const char *arg; |  | ||||||
|   int i, j, k, opt; |  | ||||||
|   dig = 1; |  | ||||||
|   symbol = "kXlatTab"; |  | ||||||
| 
 |  | ||||||
|   for (k = 1; k < argc; ++k) { |  | ||||||
|     if (argv[k][0] != '-') { |  | ||||||
|       for (i = 0; argv[k][i]; ++i) { |  | ||||||
|         /* xlat[argv[k][i] & 255] = identity ? i : dig; */ |  | ||||||
|         xlat[argv[k][i] & 255] = identity ? (argv[k][i] & 255) : dig; |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       i = 0; |  | ||||||
|     moar: |  | ||||||
|       ++i; |  | ||||||
|       if ((opt = argv[k][i])) { |  | ||||||
|         switch (opt) { |  | ||||||
|           case 's': |  | ||||||
|             symbol = GetArg(argv, i, &k); |  | ||||||
|             break; |  | ||||||
|           case 'x': |  | ||||||
|             dig = atoi(GetArg(argv, i, &k)) & 255; |  | ||||||
|             break; |  | ||||||
|           case 'i': |  | ||||||
|             Invert(); |  | ||||||
|             goto moar; |  | ||||||
|           case 'I': |  | ||||||
|             identity = !identity; |  | ||||||
|             goto moar; |  | ||||||
|           case 'n': |  | ||||||
|             Negative(); |  | ||||||
|             goto moar; |  | ||||||
|           case 'N': |  | ||||||
|             Negate(); |  | ||||||
|             goto moar; |  | ||||||
|           case 'T': |  | ||||||
|             Fill(isascii); |  | ||||||
|             goto moar; |  | ||||||
|           case 'C': |  | ||||||
|             Fill(iscntrl); |  | ||||||
|             goto moar; |  | ||||||
|           case 'A': |  | ||||||
|             Fill(isalpha); |  | ||||||
|             goto moar; |  | ||||||
|           case 'B': |  | ||||||
|             Fill(isblank); |  | ||||||
|             goto moar; |  | ||||||
|           case 'G': |  | ||||||
|             Fill(isgraph); |  | ||||||
|             goto moar; |  | ||||||
|           case 'P': |  | ||||||
|             Fill(ispunct); |  | ||||||
|             goto moar; |  | ||||||
|           case 'D': |  | ||||||
|             Fill(isdigit); |  | ||||||
|             goto moar; |  | ||||||
|           case 'U': |  | ||||||
|             Fill(isupper); |  | ||||||
|             goto moar; |  | ||||||
|           case 'L': |  | ||||||
|             Fill(islower); |  | ||||||
|             goto moar; |  | ||||||
|           default: |  | ||||||
|             fprintf(stderr, "error: unrecognized option: %c\n", opt); |  | ||||||
|             return 1; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   ////////////////////////////////////////////////////////////
 |  | ||||||
|   printf("#include \"libc/macros.internal.h\"\n"); |  | ||||||
|   printf("\n"); |  | ||||||
| 
 |  | ||||||
|   printf("//\tgenerated by:\n"); |  | ||||||
|   printf("//\t"); |  | ||||||
|   for (i = 0; i < argc; ++i) { |  | ||||||
|     if (i) printf(" "); |  | ||||||
|     printf("%s", !ArgNeedsShellQuotes(argv[i]) ? argv[i] |  | ||||||
|                                                : _gc(AddShellQuotes(argv[i]))); |  | ||||||
|   } |  | ||||||
|   printf("\n"); |  | ||||||
| 
 |  | ||||||
|   ////////////////////////////////////////////////////////////
 |  | ||||||
|   printf("//\n"); |  | ||||||
|   printf("//\t    present            absent\n"); |  | ||||||
|   printf("//\t    ────────────────   ────────────────\n"); |  | ||||||
|   for (i = 0; i < 16; ++i) { |  | ||||||
|     char16_t absent[16]; |  | ||||||
|     char16_t present[16]; |  | ||||||
|     for (j = 0; j < 16; ++j) { |  | ||||||
|       if (xlat[i * 16 + j]) { |  | ||||||
|         absent[j] = L' '; |  | ||||||
|         present[j] = Bing(i * 16 + j); |  | ||||||
|       } else { |  | ||||||
|         absent[j] = Bing(i * 16 + j); |  | ||||||
|         present[j] = L' '; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     printf("//\t    %.16hs   %.16hs   0x%02x\n", present, absent, i * 16); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   ////////////////////////////////////////////////////////////
 |  | ||||||
|   printf("//\n"); |  | ||||||
|   printf("//\tconst char %s[256] = {\n//\t", symbol); |  | ||||||
|   for (i = 0; i < 16; ++i) { |  | ||||||
|     printf("  "); |  | ||||||
|     for (j = 0; j < 16; ++j) { |  | ||||||
|       printf("%2d,", (char)xlat[i * 16 + j]); |  | ||||||
|     } |  | ||||||
|     printf(" // 0x%02x\n//\t", i * 16); |  | ||||||
|   } |  | ||||||
|   printf("};\n"); |  | ||||||
|   printf("\n"); |  | ||||||
| 
 |  | ||||||
|   ////////////////////////////////////////////////////////////
 |  | ||||||
|   printf("\t.initbss 300,_init_%s\n", symbol); |  | ||||||
|   printf("%s:\n", symbol); |  | ||||||
|   printf("\t.zero\t256\n"); |  | ||||||
|   printf("\t.endobj\t%s,globl\n", symbol); |  | ||||||
|   printf("\t.previous\n"); |  | ||||||
|   printf("\n"); |  | ||||||
| 
 |  | ||||||
|   ////////////////////////////////////////////////////////////
 |  | ||||||
|   printf("\t.initro 300,_init_%s\n", symbol); |  | ||||||
|   printf("%s.rom:\n", symbol); |  | ||||||
| 
 |  | ||||||
|   int thebloat = 0; |  | ||||||
|   int thetally = 0; |  | ||||||
|   int thecount = 0; |  | ||||||
|   int runstart = 0; |  | ||||||
|   int runchar = -1; |  | ||||||
|   int runcount = 0; |  | ||||||
|   for (i = 0;; ++i) { |  | ||||||
|     if (i < 256 && xlat[i] == runchar) { |  | ||||||
|       ++runcount; |  | ||||||
|     } else { |  | ||||||
|       if (runcount) { |  | ||||||
|         printf("\t.byte\t%-24s# %02x-%02x %hc-%hc\n", |  | ||||||
|                _gc(xasprintf("%3d,%d", runcount, runchar)), runstart, |  | ||||||
|                runstart + runcount - 1, Bing(runstart), |  | ||||||
|                Bing(runstart + runcount - 1)); |  | ||||||
|         thetally += 2; |  | ||||||
|         thecount += runcount; |  | ||||||
|       } |  | ||||||
|       if (i < 256) { |  | ||||||
|         runcount = 1; |  | ||||||
|         runchar = xlat[i]; |  | ||||||
|         runstart = i; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     if (i == 256) { |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   CHECK_EQ(256, thecount); |  | ||||||
|   printf("\t.byte\t%-24s# terminator\n", "0,0"); |  | ||||||
|   thetally += 2; |  | ||||||
|   thebloat = thetally; |  | ||||||
|   for (i = 0; (thetally + i) % 8; i += 2) { |  | ||||||
|     printf("\t.byte\t%-24s# padding\n", "0,0"); |  | ||||||
|     thebloat += 2; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   printf("\t.endobj\t%s.rom,globl\n", symbol); |  | ||||||
|   printf("\n"); |  | ||||||
| 
 |  | ||||||
|   ////////////////////////////////////////////////////////////
 |  | ||||||
|   printf("\t.init.start 300,_init_%s\n", symbol); |  | ||||||
|   printf("\tcall\trldecode\n"); |  | ||||||
|   thebloat += 5; |  | ||||||
|   int padding = 8 - thetally % 8; |  | ||||||
|   if (padding < 8) { |  | ||||||
|     if (padding >= 4) { |  | ||||||
|       thebloat += 1; |  | ||||||
|       printf("\tlodsl\n"); |  | ||||||
|       padding -= 4; |  | ||||||
|     } |  | ||||||
|     if (padding >= 2) { |  | ||||||
|       thebloat += 2; |  | ||||||
|       printf("\tlodsw\n"); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   printf("\t.init.end 300,_init_%s\n", symbol); |  | ||||||
| 
 |  | ||||||
|   ////////////////////////////////////////////////////////////
 |  | ||||||
|   printf("\n"); |  | ||||||
|   printf("//\t%d bytes total (%d%% original size)\n", thebloat, |  | ||||||
|          (int)round((double)thebloat / 256 * 100)); |  | ||||||
| } |  | ||||||
|  | @ -38,32 +38,20 @@ static const char *inpath; | ||||||
| static const char *outpath; | static const char *outpath; | ||||||
| static unsigned char *inmap; | static unsigned char *inmap; | ||||||
| 
 | 
 | ||||||
| nullterminated() static void Print(int fd, const char *s, ...) { |  | ||||||
|   va_list va; |  | ||||||
|   char buf[2048]; |  | ||||||
|   va_start(va, s); |  | ||||||
|   buf[0] = 0; |  | ||||||
|   do { |  | ||||||
|     strlcat(buf, s, sizeof(buf)); |  | ||||||
|   } while ((s = va_arg(va, const char *))); |  | ||||||
|   write(fd, buf, strlen(buf)); |  | ||||||
|   va_end(va); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static wontreturn void Die(const char *path, const char *reason) { | static wontreturn void Die(const char *path, const char *reason) { | ||||||
|   Print(2, path, ": ", reason, "\n", NULL); |   tinyprint(2, path, ": ", reason, "\n", NULL); | ||||||
|   exit(1); |   exit(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static wontreturn void SysExit(const char *path, const char *func) { | static wontreturn void SysDie(const char *path, const char *func) { | ||||||
|   const char *errstr; |   const char *errstr; | ||||||
|   if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN"; |   if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN"; | ||||||
|   Print(2, path, ": ", func, " failed with ", errstr, "\n", NULL); |   tinyprint(2, path, ": ", func, " failed with ", errstr, "\n", NULL); | ||||||
|   exit(1); |   exit(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static wontreturn void PrintUsage(int fd, int exitcode) { | static wontreturn void PrintUsage(int fd, int exitcode) { | ||||||
|   Print(fd, "\
 |   tinyprint(fd, "\
 | ||||||
| NAME\n\ | NAME\n\ | ||||||
| \n\ | \n\ | ||||||
|   Cosmopolitan Zip Copier\n\ |   Cosmopolitan Zip Copier\n\ | ||||||
|  | @ -71,7 +59,7 @@ NAME\n\ | ||||||
| SYNOPSIS\n\ | SYNOPSIS\n\ | ||||||
| \n\ | \n\ | ||||||
|   ", |   ", | ||||||
|         program_invocation_name, " [FLAGS] SRC DST\n\
 |             program_invocation_name, " [FLAGS] SRC DST\n\
 | ||||||
| \n\ | \n\ | ||||||
| DESCRIPTION\n\ | DESCRIPTION\n\ | ||||||
| \n\ | \n\ | ||||||
|  | @ -96,7 +84,7 @@ EXAMPLE\n\ | ||||||
| \n\ | \n\ | ||||||
| \n\ | \n\ | ||||||
| ", | ", | ||||||
|         NULL); |             NULL); | ||||||
|   exit(exitcode); |   exit(exitcode); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -173,10 +161,10 @@ static void CopyZip(void) { | ||||||
| 
 | 
 | ||||||
|   // write output
 |   // write output
 | ||||||
|   if ((outfd = open(outpath, O_WRONLY | O_CREAT, 0644)) == -1) { |   if ((outfd = open(outpath, O_WRONLY | O_CREAT, 0644)) == -1) { | ||||||
|     SysExit(outpath, "open"); |     SysDie(outpath, "open"); | ||||||
|   } |   } | ||||||
|   if ((outsize = lseek(outfd, 0, SEEK_END)) == -1) { |   if ((outsize = lseek(outfd, 0, SEEK_END)) == -1) { | ||||||
|     SysExit(outpath, "lseek"); |     SysDie(outpath, "lseek"); | ||||||
|   } |   } | ||||||
|   ldest = outsize; |   ldest = outsize; | ||||||
|   cdest = outsize + ltotal; |   cdest = outsize + ltotal; | ||||||
|  | @ -186,23 +174,23 @@ static void CopyZip(void) { | ||||||
|     // write local file
 |     // write local file
 | ||||||
|     length = ZIP_LFILE_SIZE(lfile); |     length = ZIP_LFILE_SIZE(lfile); | ||||||
|     if (pwrite(outfd, lfile, length, ldest) != length) { |     if (pwrite(outfd, lfile, length, ldest) != length) { | ||||||
|       SysExit(outpath, "lfile pwrite"); |       SysDie(outpath, "lfile pwrite"); | ||||||
|     } |     } | ||||||
|     ldest += length; |     ldest += length; | ||||||
|     // write directory entry
 |     // write directory entry
 | ||||||
|     length = ZIP_CFILE_HDRSIZE(cfile); |     length = ZIP_CFILE_HDRSIZE(cfile); | ||||||
|     if (pwrite(outfd, cfile, length, cdest) != length) { |     if (pwrite(outfd, cfile, length, cdest) != length) { | ||||||
|       SysExit(outpath, "lfile pwrite"); |       SysDie(outpath, "lfile pwrite"); | ||||||
|     } |     } | ||||||
|     cdest += length; |     cdest += length; | ||||||
|   } |   } | ||||||
|   WRITE32LE(eocd + kZipCdirOffsetOffset, outsize + ltotal); |   WRITE32LE(eocd + kZipCdirOffsetOffset, outsize + ltotal); | ||||||
|   length = ZIP_CDIR_HDRSIZE(eocd); |   length = ZIP_CDIR_HDRSIZE(eocd); | ||||||
|   if (pwrite(outfd, eocd, length, cdest) != length) { |   if (pwrite(outfd, eocd, length, cdest) != length) { | ||||||
|     SysExit(outpath, "eocd pwrite"); |     SysDie(outpath, "eocd pwrite"); | ||||||
|   } |   } | ||||||
|   if (close(outfd)) { |   if (close(outfd)) { | ||||||
|     SysExit(outpath, "close"); |     SysDie(outpath, "close"); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -213,23 +201,23 @@ int main(int argc, char *argv[]) { | ||||||
|   } |   } | ||||||
|   GetOpts(argc, argv); |   GetOpts(argc, argv); | ||||||
|   if ((infd = open(inpath, O_RDONLY)) == -1) { |   if ((infd = open(inpath, O_RDONLY)) == -1) { | ||||||
|     SysExit(inpath, "open"); |     SysDie(inpath, "open"); | ||||||
|   } |   } | ||||||
|   if ((insize = lseek(infd, 0, SEEK_END)) == -1) { |   if ((insize = lseek(infd, 0, SEEK_END)) == -1) { | ||||||
|     SysExit(inpath, "lseek"); |     SysDie(inpath, "lseek"); | ||||||
|   } |   } | ||||||
|   if (!insize) { |   if (!insize) { | ||||||
|     Die(inpath, "file is empty"); |     Die(inpath, "file is empty"); | ||||||
|   } |   } | ||||||
|   if ((inmap = mmap(0, insize, PROT_READ | PROT_WRITE, MAP_PRIVATE, infd, 0)) == |   if ((inmap = mmap(0, insize, PROT_READ | PROT_WRITE, MAP_PRIVATE, infd, 0)) == | ||||||
|       MAP_FAILED) { |       MAP_FAILED) { | ||||||
|     SysExit(inpath, "mmap"); |     SysDie(inpath, "mmap"); | ||||||
|   } |   } | ||||||
|   CopyZip(); |   CopyZip(); | ||||||
|   if (munmap(inmap, insize)) { |   if (munmap(inmap, insize)) { | ||||||
|     SysExit(inpath, "munmap"); |     SysDie(inpath, "munmap"); | ||||||
|   } |   } | ||||||
|   if (close(infd)) { |   if (close(infd)) { | ||||||
|     SysExit(inpath, "close"); |     SysDie(inpath, "close"); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -21,7 +21,6 @@ | ||||||
| #include "libc/elf/def.h" | #include "libc/elf/def.h" | ||||||
| #include "libc/fmt/conv.h" | #include "libc/fmt/conv.h" | ||||||
| #include "libc/fmt/libgen.h" | #include "libc/fmt/libgen.h" | ||||||
| #include "libc/intrin/kprintf.h" |  | ||||||
| #include "libc/limits.h" | #include "libc/limits.h" | ||||||
| #include "libc/log/check.h" | #include "libc/log/check.h" | ||||||
| #include "libc/log/log.h" | #include "libc/log/log.h" | ||||||
|  | @ -52,15 +51,16 @@ int strip_components_; | ||||||
| const char *path_prefix_; | const char *path_prefix_; | ||||||
| struct timespec timestamp; | struct timespec timestamp; | ||||||
| 
 | 
 | ||||||
| wontreturn void PrintUsage(int rc) { | wontreturn void PrintUsage(int fd, int rc) { | ||||||
|   kprintf("\n\
 |   tinyprint(fd, "\n\
 | ||||||
| NAME\n\ | NAME\n\ | ||||||
| \n\ | \n\ | ||||||
|   Cosmpolitan Zip File Compiler\n\ |   Cosmpolitan Zip File Compiler\n\ | ||||||
| \n\ | \n\ | ||||||
| SYNOPSIS\n\ | SYNOPSIS\n\ | ||||||
| \n\ | \n\ | ||||||
|   %s [FLAGS] FILE...\n\ |   ", | ||||||
|  |             program_invocation_name, " [FLAGS] FILE...\n\
 | ||||||
| \n\ | \n\ | ||||||
| DESCRIPTION\n\ | DESCRIPTION\n\ | ||||||
| \n\ | \n\ | ||||||
|  | @ -80,7 +80,7 @@ FLAGS\n\ | ||||||
|   -y SYMBOL       generate yoink for symbol (default __zip_eocd)\n\ |   -y SYMBOL       generate yoink for symbol (default __zip_eocd)\n\ | ||||||
| \n\ | \n\ | ||||||
| ", | ", | ||||||
|           program_invocation_name); |             NULL); | ||||||
|   exit(rc); |   exit(rc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -117,17 +117,18 @@ void GetOpts(int *argc, char ***argv) { | ||||||
|         break; |         break; | ||||||
|       case '?': |       case '?': | ||||||
|       case 'h': |       case 'h': | ||||||
|         PrintUsage(EXIT_SUCCESS); |         PrintUsage(1, EXIT_SUCCESS); | ||||||
|       default: |       default: | ||||||
|         PrintUsage(EX_USAGE); |         PrintUsage(2, EX_USAGE); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   *argc -= optind; |   *argc -= optind; | ||||||
|   *argv += optind; |   *argv += optind; | ||||||
|   if (!outpath_) { |   if (!outpath_) { | ||||||
|     kprintf("error: no output path specified\n" |     tinyprint(2, | ||||||
|             "run %s -h for usage\n", |               "error: no output path specified\n" | ||||||
|             program_invocation_name); |               "run ", | ||||||
|  |               program_invocation_name, " -h for usage\n", NULL); | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,101 +0,0 @@ | ||||||
| #include "libc/nt/struct/peb.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| 
 |  | ||||||
| int main() { |  | ||||||
|   printf("InheritedAddressSpace = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, InheritedAddressSpace)); |  | ||||||
|   printf("ReadImageFileExecOptions = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ReadImageFileExecOptions)); |  | ||||||
|   printf("BeingDebugged = 0x%x\n", offsetof(struct NtPeb, BeingDebugged)); |  | ||||||
|   printf("Mutant = 0x%x\n", offsetof(struct NtPeb, Mutant)); |  | ||||||
|   printf("ImageBaseAddress = 0x%x\n", offsetof(struct NtPeb, ImageBaseAddress)); |  | ||||||
|   printf("Ldr = 0x%x\n", offsetof(struct NtPeb, Ldr)); |  | ||||||
|   printf("ProcessParameters = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ProcessParameters)); |  | ||||||
|   printf("SubSystemData = 0x%x\n", offsetof(struct NtPeb, SubSystemData)); |  | ||||||
|   printf("ProcessHeap = 0x%x\n", offsetof(struct NtPeb, ProcessHeap)); |  | ||||||
|   printf("FastPebLock = 0x%x\n", offsetof(struct NtPeb, FastPebLock)); |  | ||||||
|   printf("KernelCallbackTable = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, KernelCallbackTable)); |  | ||||||
|   printf("UserSharedInfoPtr = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, UserSharedInfoPtr)); |  | ||||||
|   printf("SystemReserved = 0x%x\n", offsetof(struct NtPeb, SystemReserved)); |  | ||||||
|   printf("__wut6 = 0x%x\n", offsetof(struct NtPeb, __wut6)); |  | ||||||
|   printf("__wut7 = 0x%x\n", offsetof(struct NtPeb, __wut7)); |  | ||||||
|   printf("TlsExpansionCounter = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, TlsExpansionCounter)); |  | ||||||
|   printf("TlsBitmap = 0x%x\n", offsetof(struct NtPeb, TlsBitmap)); |  | ||||||
|   printf("TlsBitmapBits = 0x%x\n", offsetof(struct NtPeb, TlsBitmapBits)); |  | ||||||
|   printf("ReadOnlySharedMemoryBase = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ReadOnlySharedMemoryBase)); |  | ||||||
|   printf("ReadOnlyStaticServerData = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ReadOnlyStaticServerData)); |  | ||||||
|   printf("AnsiCodePageData = 0x%x\n", offsetof(struct NtPeb, AnsiCodePageData)); |  | ||||||
|   printf("OemCodePageData = 0x%x\n", offsetof(struct NtPeb, OemCodePageData)); |  | ||||||
|   printf("UnicodeCaseTableData = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, UnicodeCaseTableData)); |  | ||||||
|   printf("NumberOfProcessors = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, NumberOfProcessors)); |  | ||||||
|   printf("NtGlobalFlag = 0x%x\n", offsetof(struct NtPeb, NtGlobalFlag)); |  | ||||||
|   printf("CriticalSectionTimeout = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, CriticalSectionTimeout)); |  | ||||||
|   printf("HeapSegmentReserve = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, HeapSegmentReserve)); |  | ||||||
|   printf("HeapSegmentCommit = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, HeapSegmentCommit)); |  | ||||||
|   printf("HeapDeCommitTotalFreeThreshold = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, HeapDeCommitTotalFreeThreshold)); |  | ||||||
|   printf("HeapDeCommitFreeBlockThreshold = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, HeapDeCommitFreeBlockThreshold)); |  | ||||||
|   printf("NumberOfHeaps = 0x%x\n", offsetof(struct NtPeb, NumberOfHeaps)); |  | ||||||
|   printf("MaximumNumberOfHeaps = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, MaximumNumberOfHeaps)); |  | ||||||
|   printf("ProcessHeaps = 0x%x\n", offsetof(struct NtPeb, ProcessHeaps)); |  | ||||||
|   printf("GdiSharedHandleTable = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, GdiSharedHandleTable)); |  | ||||||
|   printf("ProcessStarterHelper = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ProcessStarterHelper)); |  | ||||||
|   printf("GdiDCAttributeList = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, GdiDCAttributeList)); |  | ||||||
|   printf("LoaderLock = 0x%x\n", offsetof(struct NtPeb, LoaderLock)); |  | ||||||
|   printf("OSMajorVersion = 0x%x\n", offsetof(struct NtPeb, OSMajorVersion)); |  | ||||||
|   printf("OSMinorVersion = 0x%x\n", offsetof(struct NtPeb, OSMinorVersion)); |  | ||||||
|   printf("OSVersion = 0x%x\n", offsetof(struct NtPeb, OSVersion)); |  | ||||||
|   printf("OSBuildNumber = 0x%x\n", offsetof(struct NtPeb, OSBuildNumber)); |  | ||||||
|   printf("OSCSDVersion = 0x%x\n", offsetof(struct NtPeb, OSCSDVersion)); |  | ||||||
|   printf("OSPlatformId = 0x%x\n", offsetof(struct NtPeb, OSPlatformId)); |  | ||||||
|   printf("ImageSubsystem = 0x%x\n", offsetof(struct NtPeb, ImageSubsystem)); |  | ||||||
|   printf("ImageSubsystemMajorVersion = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ImageSubsystemMajorVersion)); |  | ||||||
|   printf("ImageSubsystemMinorVersion = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ImageSubsystemMinorVersion)); |  | ||||||
|   printf("ImageProcessAffinityMask = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ImageProcessAffinityMask)); |  | ||||||
|   printf("ActiveProcessAffinityMask = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ActiveProcessAffinityMask)); |  | ||||||
|   printf("GdiHandleBuffer = 0x%x\n", offsetof(struct NtPeb, GdiHandleBuffer)); |  | ||||||
|   printf("PostProcessInitRoutine = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, PostProcessInitRoutine)); |  | ||||||
|   printf("TlsExpansionBitmap = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, TlsExpansionBitmap)); |  | ||||||
|   printf("TlsExpansionBitmapBits = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, TlsExpansionBitmapBits)); |  | ||||||
|   printf("SessionId = 0x%x\n", offsetof(struct NtPeb, SessionId)); |  | ||||||
|   printf("AppCompatFlags = 0x%x\n", offsetof(struct NtPeb, AppCompatFlags)); |  | ||||||
|   printf("AppCompatFlagsUser = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, AppCompatFlagsUser)); |  | ||||||
|   printf("pShimData = 0x%x\n", offsetof(struct NtPeb, pShimData)); |  | ||||||
|   printf("AppCompatInfo = 0x%x\n", offsetof(struct NtPeb, AppCompatInfo)); |  | ||||||
|   printf("CSDVersion = 0x%x\n", offsetof(struct NtPeb, CSDVersion)); |  | ||||||
|   printf("ActivationContextData = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ActivationContextData)); |  | ||||||
|   printf("ProcessAssemblyStorageMap = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, ProcessAssemblyStorageMap)); |  | ||||||
|   printf("SystemDefaultActivationContextData = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, SystemDefaultActivationContextData)); |  | ||||||
|   printf("SystemAssemblyStorageMap = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, SystemAssemblyStorageMap)); |  | ||||||
|   printf("MinimumStackCommit = 0x%x\n", |  | ||||||
|          offsetof(struct NtPeb, MinimumStackCommit)); |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,202 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2021 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.                                                │ |  | ||||||
| ╚──────────────────────────────────────────────────────────────────────────────┘ |  | ||||||
| 
 |  | ||||||
|   THIS PROGRAM TURNS TEXT LIKE THIS |  | ||||||
| 
 |  | ||||||
|    +------------------------------------------------------------------------+ |  | ||||||
|    | Button     | Name        | Go to                          | From 1.2.3 | |  | ||||||
|    |            |             |                                | go to      | |  | ||||||
|    |------------+-------------+--------------------------------+------------| |  | ||||||
|    |   [ < ]    |    Back     | previous section in reading    | 1.2.2      | |  | ||||||
|    |            |             | order                          |            | |  | ||||||
|    |------------+-------------+--------------------------------+------------| |  | ||||||
|    |   [ > ]    |   Forward   | next section in reading order  | 1.2.4      | |  | ||||||
|    |------------+-------------+--------------------------------+------------| |  | ||||||
|    |   [ << ]   |  FastBack   | previous or up-and-previous    | 1.1        | |  | ||||||
|    |            |             | section                        |            | |  | ||||||
|    |------------+-------------+--------------------------------+------------| |  | ||||||
|    |   [ Up ]   |     Up      | up section                     | 1.2        | |  | ||||||
|    |------------+-------------+--------------------------------+------------| |  | ||||||
|    |   [ >> ]   | FastForward | next or up-and-next section    | 1.3        | |  | ||||||
|    |------------+-------------+--------------------------------+------------| |  | ||||||
|    |   [Top]    |     Top     | cover (top) of document        |            | |  | ||||||
|    |------------+-------------+--------------------------------+------------| |  | ||||||
|    | [Contents] |  Contents   | table of contents              |            | |  | ||||||
|    |------------+-------------+--------------------------------+------------| |  | ||||||
|    |  [Index]   |    Index    | concept index                  |            | |  | ||||||
|    |------------+-------------+--------------------------------+------------| |  | ||||||
|    |   [ ? ]    |    About    | this page                      |            | |  | ||||||
|    +------------------------------------------------------------------------+ |  | ||||||
| 
 |  | ||||||
|   INTO THIS |  | ||||||
| 
 |  | ||||||
|    ┌────────────┬─────────────┬────────────────────────────────┬────────────┐ |  | ||||||
|    │ Button     │ Name        │ Go to                          │ From 1.2.3 │ |  | ||||||
|    │            │             │                                │ go to      │ |  | ||||||
|    ├────────────┼─────────────┼────────────────────────────────┼────────────┤ |  | ||||||
|    │   [ < ]    │    Back     │ previous section in reading    │ 1.2.2      │ |  | ||||||
|    │            │             │ order                          │            │ |  | ||||||
|    ├────────────┼─────────────┼────────────────────────────────┼────────────┤ |  | ||||||
|    │   [ > ]    │   Forward   │ next section in reading order  │ 1.2.4      │ |  | ||||||
|    ├────────────┼─────────────┼────────────────────────────────┼────────────┤ |  | ||||||
|    │   [ << ]   │  FastBack   │ previous or up─and─previous    │ 1.1        │ |  | ||||||
|    │            │             │ section                        │            │ |  | ||||||
|    ├────────────┼─────────────┼────────────────────────────────┼────────────┤ |  | ||||||
|    │   [ Up ]   │     Up      │ up section                     │ 1.2        │ |  | ||||||
|    ├────────────┼─────────────┼────────────────────────────────┼────────────┤ |  | ||||||
|    │   [ >> ]   │ FastForward │ next or up─and─next section    │ 1.3        │ |  | ||||||
|    ├────────────┼─────────────┼────────────────────────────────┼────────────┤ |  | ||||||
|    │   [Top]    │     Top     │ cover (top) of document        │            │ |  | ||||||
|    ├────────────┼─────────────┼────────────────────────────────┼────────────┤ |  | ||||||
|    │ [Contents] │  Contents   │ table of contents              │            │ |  | ||||||
|    ├────────────┼─────────────┼────────────────────────────────┼────────────┤ |  | ||||||
|    │  [Index]   │    Index    │ concept index                  │            │ |  | ||||||
|    ├────────────┼─────────────┼────────────────────────────────┼────────────┤ |  | ||||||
|    │   [ ? ]    │    About    │ this page                      │            │ |  | ||||||
|    └────────────┴─────────────┴────────────────────────────────┴────────────┘ */ |  | ||||||
| #include "libc/macros.internal.h" |  | ||||||
| #include "libc/mem/gc.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/str/strwidth.h" |  | ||||||
| #include "libc/x/x.h" |  | ||||||
| #include "libc/x/xasprintf.h" |  | ||||||
| #include "libc/x/xgetline.h" |  | ||||||
| 
 |  | ||||||
| #define IsSpace(C)  ((C) == ' ') |  | ||||||
| #define IsPipe(C)   ((C) == '|' || (C) == u'│') |  | ||||||
| #define IsPlus(C)   ((C) == '+' || (C) == u'┼') |  | ||||||
| #define IsHyphen(C) ((C) == '-' || (C) == u'─') |  | ||||||
| #define IsTick(C)   ((C) == '`' || (C) == u'└') |  | ||||||
| #define IsPipe(C)   ((C) == '|' || (C) == u'│') |  | ||||||
| #define IsEquals(C) ((C) == '=' || (C) == u'═') |  | ||||||
| 
 |  | ||||||
| int n; |  | ||||||
| int yn; |  | ||||||
| int xn; |  | ||||||
| 
 |  | ||||||
| FILE *f; |  | ||||||
| bool *V; |  | ||||||
| char **T; |  | ||||||
| char16_t **L; |  | ||||||
| 
 |  | ||||||
| static void DoIt(int y, int x) { |  | ||||||
|   if (V[y * (xn + 1) + x]) return; |  | ||||||
|   V[y * (xn + 1) + x] = 1; |  | ||||||
|   if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) && |  | ||||||
|       IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'┼'; |  | ||||||
|   } else if (IsPipe(L[y - 1][x]) && IsEquals(L[y][x - 1]) && IsPlus(L[y][x]) && |  | ||||||
|              IsEquals(L[y][x + 1]) && IsPipe(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'╪'; |  | ||||||
|   } else if (IsSpace(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && |  | ||||||
|              IsHyphen(L[y][x]) && IsHyphen(L[y][x + 1]) && |  | ||||||
|              IsPipe(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'┬'; |  | ||||||
|   } else if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && |  | ||||||
|              IsHyphen(L[y][x]) && IsHyphen(L[y][x + 1]) && |  | ||||||
|              IsSpace(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'┴'; |  | ||||||
|   } else if (IsPipe(L[y - 1][x]) && IsSpace(L[y][x - 1]) && IsPipe(L[y][x]) && |  | ||||||
|              IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'├'; |  | ||||||
|   } else if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPipe(L[y][x]) && |  | ||||||
|              IsSpace(L[y][x + 1]) && IsPipe(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'┤'; |  | ||||||
|   } else if (IsSpace(L[y - 1][x]) && IsSpace(L[y][x - 1]) && IsPlus(L[y][x]) && |  | ||||||
|              IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'┌'; |  | ||||||
|   } else if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) && |  | ||||||
|              IsSpace(L[y][x + 1]) && IsSpace(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'┘'; |  | ||||||
|   } else if (IsSpace(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) && |  | ||||||
|              IsSpace(L[y][x + 1]) && IsPipe(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'┐'; |  | ||||||
|   } else if (IsPipe(L[y - 1][x]) && IsSpace(L[y][x - 1]) && IsPlus(L[y][x]) && |  | ||||||
|              IsHyphen(L[y][x + 1]) && IsSpace(L[y + 1][x])) { |  | ||||||
|     L[y][x] = u'└'; |  | ||||||
|   } else if (IsTick(L[y][x]) && IsPipe(L[y - 1][x]) && IsHyphen(L[y][x + 1]) && |  | ||||||
|              IsSpace(L[y + 1][x]) && IsSpace(L[y][x - 1])) { |  | ||||||
|     L[y][x] = u'└'; |  | ||||||
|   } else if (IsHyphen(L[y][x])) { |  | ||||||
|     L[y][x] = u'─'; |  | ||||||
|   } else if (IsPipe(L[y][x])) { |  | ||||||
|     L[y][x] = u'│'; |  | ||||||
|   } else if (IsEquals(L[y][x])) { |  | ||||||
|     L[y][x] = u'═'; |  | ||||||
|   } else { |  | ||||||
|     return; |  | ||||||
|   } |  | ||||||
|   DoIt(y - 1, x + 0); |  | ||||||
|   DoIt(y + 1, x + 0); |  | ||||||
|   DoIt(y + 0, x - 1); |  | ||||||
|   DoIt(y + 0, x + 1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   char *s; |  | ||||||
|   int y, x; |  | ||||||
|   ShowCrashReports(); |  | ||||||
|   f = stdin; |  | ||||||
|   while ((s = _chomp(xgetline(f)))) { |  | ||||||
|     n = strwidth(s, 0); |  | ||||||
|     xn = MAX(xn, n); |  | ||||||
|     T = xrealloc(T, ++yn * sizeof(*T)); |  | ||||||
|     T[yn - 1] = s; |  | ||||||
|   } |  | ||||||
|   xn += 1000; |  | ||||||
|   L = xmalloc((yn + 2) * sizeof(*L)); |  | ||||||
|   L[0] = utf8to16(_gc(xasprintf(" %*s ", xn, " ")), -1, 0); |  | ||||||
|   for (y = 0; y < yn; ++y) { |  | ||||||
|     s = xasprintf(" %s%*s ", T[y], xn - n, " "); |  | ||||||
|     L[y + 1] = utf8to16(s, -1, 0); |  | ||||||
|     free(T[y]); |  | ||||||
|     free(s); |  | ||||||
|   } |  | ||||||
|   L[yn + 2 - 1] = utf8to16(_gc(xasprintf(" %*s ", xn, " ")), -1, 0); |  | ||||||
|   free(T); |  | ||||||
|   V = xcalloc((yn + 1) * (xn + 1), 1); |  | ||||||
|   for (y = 1; y <= yn; ++y) { |  | ||||||
|     for (x = 1; x <= xn; ++x) { |  | ||||||
|       if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) && |  | ||||||
|           IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) { |  | ||||||
|         DoIt(y, x); |  | ||||||
|       } |  | ||||||
|       if (IsTick(L[y][x]) && IsPipe(L[y - 1][x]) && IsHyphen(L[y][x + 1]) && |  | ||||||
|           IsSpace(L[y + 1][x]) && IsSpace(L[y][x - 1])) { |  | ||||||
|         DoIt(y, x); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   for (y = 1; y + 1 < yn; ++y) { |  | ||||||
|     s = utf16to8(L[y], -1, 0); |  | ||||||
|     n = strlen(s); |  | ||||||
|     while (n && s[n - 1] == ' ') s[n - 1] = 0, --n; |  | ||||||
|     puts(s + 1); |  | ||||||
|     free(s); |  | ||||||
|   } |  | ||||||
|   for (y = 0; y < yn; ++y) { |  | ||||||
|     free(L[y]); |  | ||||||
|   } |  | ||||||
|   free(L); |  | ||||||
|   free(V); |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,284 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2021 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 "libc/calls/calls.h" |  | ||||||
| #include "libc/calls/struct/stat.h" |  | ||||||
| #include "libc/fmt/conv.h" |  | ||||||
| #include "libc/intrin/safemacros.internal.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/log/log.h" |  | ||||||
| #include "libc/mem/gc.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/sysv/consts/map.h" |  | ||||||
| #include "libc/sysv/consts/o.h" |  | ||||||
| #include "libc/sysv/consts/prot.h" |  | ||||||
| #include "libc/x/xasprintf.h" |  | ||||||
| #include "libc/x/xiso8601.h" |  | ||||||
| #include "libc/zip.internal.h" |  | ||||||
| #include "tool/decode/lib/asmcodegen.h" |  | ||||||
| #include "tool/decode/lib/disassemblehex.h" |  | ||||||
| #include "tool/decode/lib/zipnames.h" |  | ||||||
| 
 |  | ||||||
| char *FormatDosDate(uint16_t dosdate) { |  | ||||||
|   return xasprintf("%04u-%02u-%02u", ((dosdate >> 9) & 0b1111111) + 1980, |  | ||||||
|                    (dosdate >> 5) & 0b1111, dosdate & 0b11111); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| char *FormatDosTime(uint16_t dostime) { |  | ||||||
|   return xasprintf("%02u:%02u:%02u", (dostime >> 11) & 0b11111, |  | ||||||
|                    (dostime >> 5) & 0b111111, (dostime << 1) & 0b111110); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowGeneralFlag(uint16_t generalflag) { |  | ||||||
|   puts("\
 |  | ||||||
| /	              ┌─utf8\n\ |  | ||||||
| /	              │    ┌─strong encryption\n\ |  | ||||||
| /	              │    │┌─compressed patch data\n\ |  | ||||||
| /	              │    ││ ┌─crc and size go after file content\n\ |  | ||||||
| /	              │    ││ │┌─{normal,max,fast,superfast}\n\ |  | ||||||
| /	              │    ││ ││ ┌─encrypted\n\ |  | ||||||
| /	          rrrr│uuuu││r│├┐│"); |  | ||||||
|   show(".short", format(b1, "0b%016b", generalflag), "generalflag"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowCompressionMethod(uint16_t compressmethod) { |  | ||||||
|   show(".short", |  | ||||||
|        firstnonnull(findnamebyid(kZipCompressionNames, compressmethod), |  | ||||||
|                     format(b1, "%hu", compressmethod)), |  | ||||||
|        "compressionmethod"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowTimestamp(uint16_t time, uint16_t date) { |  | ||||||
|   show(".short", format(b1, "%#04hx", time), |  | ||||||
|        _gc(xasprintf("%s (%s)", "lastmodifiedtime", _gc(FormatDosTime(time))))); |  | ||||||
|   show(".short", format(b1, "%#04hx", date), |  | ||||||
|        _gc(xasprintf("%s (%s)", "lastmodifieddate", _gc(FormatDosDate(date))))); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowNtfs(uint8_t *ntfs, size_t n) { |  | ||||||
|   struct timespec mtime, atime, ctime; |  | ||||||
|   mtime = WindowsTimeToTimeSpec(READ64LE(ntfs + 8)); |  | ||||||
|   atime = WindowsTimeToTimeSpec(READ64LE(ntfs + 16)); |  | ||||||
|   ctime = WindowsTimeToTimeSpec(READ64LE(ntfs + 24)); |  | ||||||
|   show(".long", _gc(xasprintf("%d", READ32LE(ntfs))), "ntfs reserved"); |  | ||||||
|   show(".short", _gc(xasprintf("0x%04x", READ16LE(ntfs + 4))), |  | ||||||
|        "ntfs attribute tag value #1"); |  | ||||||
|   show(".short", _gc(xasprintf("%hu", READ16LE(ntfs + 6))), |  | ||||||
|        "ntfs attribute tag size"); |  | ||||||
|   show(".quad", _gc(xasprintf("%lu", READ64LE(ntfs + 8))), |  | ||||||
|        _gc(xasprintf("%s (%s)", "ntfs last modified time", |  | ||||||
|                      _gc(xiso8601(&mtime))))); |  | ||||||
|   show(".quad", _gc(xasprintf("%lu", READ64LE(ntfs + 16))), |  | ||||||
|        _gc(xasprintf("%s (%s)", "ntfs last access time", |  | ||||||
|                      _gc(xiso8601(&atime))))); |  | ||||||
|   show(".quad", _gc(xasprintf("%lu", READ64LE(ntfs + 24))), |  | ||||||
|        _gc(xasprintf("%s (%s)", "ntfs creation time", _gc(xiso8601(&ctime))))); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowExtendedTimestamp(uint8_t *p, size_t n, bool islocal) { |  | ||||||
|   int flag; |  | ||||||
|   if (n) { |  | ||||||
|     --n; |  | ||||||
|     flag = *p++; |  | ||||||
|     show(".byte", _gc(xasprintf("0b%03hhb", flag)), "fields present in local"); |  | ||||||
|     if ((flag & 1) && n >= 4) { |  | ||||||
|       show(".long", _gc(xasprintf("%u", READ32LE(p))), |  | ||||||
|            _gc(xasprintf("%s (%s)", "last modified", |  | ||||||
|                          _gc(xiso8601(&(struct timespec){READ32LE(p)}))))); |  | ||||||
|       p += 4; |  | ||||||
|       n -= 4; |  | ||||||
|     } |  | ||||||
|     flag >>= 1; |  | ||||||
|     if (islocal) { |  | ||||||
|       if ((flag & 1) && n >= 4) { |  | ||||||
|         show(".long", _gc(xasprintf("%u", READ32LE(p))), |  | ||||||
|              _gc(xasprintf("%s (%s)", "access time", |  | ||||||
|                            _gc(xiso8601(&(struct timespec){READ32LE(p)}))))); |  | ||||||
|         p += 4; |  | ||||||
|         n -= 4; |  | ||||||
|       } |  | ||||||
|       flag >>= 1; |  | ||||||
|       if ((flag & 1) && n >= 4) { |  | ||||||
|         show(".long", _gc(xasprintf("%u", READ32LE(p))), |  | ||||||
|              _gc(xasprintf("%s (%s)", "creation time", |  | ||||||
|                            _gc(xiso8601(&(struct timespec){READ32LE(p)}))))); |  | ||||||
|         p += 4; |  | ||||||
|         n -= 4; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowZip64(uint8_t *p, size_t n, bool islocal) { |  | ||||||
|   if (n >= 8) { |  | ||||||
|     show(".quad", _gc(xasprintf("%lu", READ64LE(p))), |  | ||||||
|          _gc(xasprintf("uncompressed size (%,ld)", READ64LE(p)))); |  | ||||||
|   } |  | ||||||
|   if (n >= 16) { |  | ||||||
|     show(".quad", _gc(xasprintf("%lu", READ64LE(p + 8))), |  | ||||||
|          _gc(xasprintf("compressed size (%,ld)", READ64LE(p + 8)))); |  | ||||||
|   } |  | ||||||
|   if (n >= 24) { |  | ||||||
|     show(".quad", _gc(xasprintf("%lu", READ64LE(p + 16))), |  | ||||||
|          _gc(xasprintf("lfile hdr offset (%,ld)", READ64LE(p + 16)))); |  | ||||||
|   } |  | ||||||
|   if (n >= 28) { |  | ||||||
|     show(".long", _gc(xasprintf("%u", READ32LE(p + 24))), "disk number"); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowInfoZipNewUnixExtra(uint8_t *p, size_t n, bool islocal) { |  | ||||||
|   if (p[0] == 1 && p[1] == 4 && p[6] == 4) { |  | ||||||
|     show(".byte", "1", "version"); |  | ||||||
|     show(".byte", "4", "uid length"); |  | ||||||
|     show(".long", _gc(xasprintf("%u", READ32LE(p + 2))), "uid"); |  | ||||||
|     show(".byte", "4", "gid length"); |  | ||||||
|     show(".long", _gc(xasprintf("%u", READ32LE(p + 7))), "gid"); |  | ||||||
|   } else { |  | ||||||
|     disassemblehex(p, n, stdout); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowExtra(uint8_t *extra, bool islocal) { |  | ||||||
|   switch (ZIP_EXTRA_HEADERID(extra)) { |  | ||||||
|     case kZipExtraNtfs: |  | ||||||
|       ShowNtfs(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra)); |  | ||||||
|       break; |  | ||||||
|     case kZipExtraExtendedTimestamp: |  | ||||||
|       ShowExtendedTimestamp(ZIP_EXTRA_CONTENT(extra), |  | ||||||
|                             ZIP_EXTRA_CONTENTSIZE(extra), islocal); |  | ||||||
|       break; |  | ||||||
|     case kZipExtraZip64: |  | ||||||
|       ShowZip64(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra), |  | ||||||
|                 islocal); |  | ||||||
|       break; |  | ||||||
|     case kZipExtraInfoZipNewUnixExtra: |  | ||||||
|       ShowInfoZipNewUnixExtra(ZIP_EXTRA_CONTENT(extra), |  | ||||||
|                               ZIP_EXTRA_CONTENTSIZE(extra), islocal); |  | ||||||
|       break; |  | ||||||
|     default: |  | ||||||
|       disassemblehex(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra), |  | ||||||
|                      stdout); |  | ||||||
|       break; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowExtras(uint8_t *extras, uint16_t extrassize, bool islocal) { |  | ||||||
|   int i; |  | ||||||
|   bool first; |  | ||||||
|   uint8_t *p, *pe; |  | ||||||
|   if (extrassize) { |  | ||||||
|     first = true; |  | ||||||
|     for (p = extras, pe = extras + extrassize, i = 0; p < pe; |  | ||||||
|          p += ZIP_EXTRA_SIZE(p), ++i) { |  | ||||||
|       show(".short", |  | ||||||
|            firstnonnull(findnamebyid(kZipExtraNames, ZIP_EXTRA_HEADERID(p)), |  | ||||||
|                         _gc(xasprintf("0x%04hx", ZIP_EXTRA_HEADERID(p)))), |  | ||||||
|            _gc(xasprintf("%s[%d].%s", "extras", i, "headerid"))); |  | ||||||
|       show(".short", _gc(xasprintf("%df-%df", (i + 2) * 10, (i + 1) * 10)), |  | ||||||
|            _gc(xasprintf("%s[%d].%s (%hd %s)", "extras", i, "contentsize", |  | ||||||
|                          ZIP_EXTRA_CONTENTSIZE(p), "bytes"))); |  | ||||||
|       if (first) { |  | ||||||
|         first = false; |  | ||||||
|         printf("%d:", (i + 1) * 10); |  | ||||||
|       } |  | ||||||
|       ShowExtra(p, islocal); |  | ||||||
|       printf("%d:", (i + 2) * 10); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   putchar('\n'); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ShowLocalFileHeader(uint8_t *lf, uint16_t idx) { |  | ||||||
|   printf("\n/\t%s #%hu (%zu %s)\n", "local file", idx + 1, |  | ||||||
|          ZIP_LFILE_HDRSIZE(lf), "bytes"); |  | ||||||
|   show(".ascii", format(b1, "%`'.*s", 4, lf), "magic"); |  | ||||||
|   show(".byte", |  | ||||||
|        firstnonnull(findnamebyid(kZipEraNames, ZIP_LFILE_VERSIONNEED(lf)), |  | ||||||
|                     _gc(xasprintf("%d", ZIP_LFILE_VERSIONNEED(lf)))), |  | ||||||
|        "pkzip version need"); |  | ||||||
|   show(".byte", |  | ||||||
|        firstnonnull(findnamebyid(kZipOsNames, ZIP_LFILE_OSNEED(lf)), |  | ||||||
|                     _gc(xasprintf("%d", ZIP_LFILE_OSNEED(lf)))), |  | ||||||
|        "os need"); |  | ||||||
|   ShowGeneralFlag(ZIP_LFILE_GENERALFLAG(lf)); |  | ||||||
|   ShowCompressionMethod(ZIP_LFILE_COMPRESSIONMETHOD(lf)); |  | ||||||
|   ShowTimestamp(ZIP_LFILE_LASTMODIFIEDTIME(lf), ZIP_LFILE_LASTMODIFIEDDATE(lf)); |  | ||||||
|   show( |  | ||||||
|       ".long", |  | ||||||
|       format(b1, "%#x", ZIP_LFILE_CRC32(lf)), _gc(xasprintf("%s (%#x)", "crc32z", GetZipLfileCompressedSize(lf) /* crc32_z(0, ZIP_LFILE_CONTENT(lf), GetZipLfileCompressedSize(lf)) */))); |  | ||||||
|   if (ZIP_LFILE_COMPRESSEDSIZE(lf) == 0xFFFFFFFF) { |  | ||||||
|     show(".long", "0xFFFFFFFF", "compressedsize (zip64)"); |  | ||||||
|   } else { |  | ||||||
|     show(".long", "3f-2f", |  | ||||||
|          format(b1, "%s (%u %s)", "compressedsize", |  | ||||||
|                 ZIP_LFILE_COMPRESSEDSIZE(lf), "bytes")); |  | ||||||
|   } |  | ||||||
|   show(".long", |  | ||||||
|        ZIP_LFILE_UNCOMPRESSEDSIZE(lf) == 0xFFFFFFFF |  | ||||||
|            ? "0xFFFFFFFF" |  | ||||||
|            : format(b1, "%u", ZIP_LFILE_UNCOMPRESSEDSIZE(lf)), |  | ||||||
|        "uncompressedsize"); |  | ||||||
|   show(".short", "1f-0f", |  | ||||||
|        format(b1, "%s (%hu %s)", "namesize", ZIP_LFILE_NAMESIZE(lf), "bytes")); |  | ||||||
|   show( |  | ||||||
|       ".short", "2f-1f", |  | ||||||
|       format(b1, "%s (%hu %s)", "extrasize", ZIP_LFILE_EXTRASIZE(lf), "bytes")); |  | ||||||
|   printf("0:"); |  | ||||||
|   show(".ascii", |  | ||||||
|        format(b1, "%`'s", |  | ||||||
|               _gc(strndup(ZIP_LFILE_NAME(lf), ZIP_LFILE_NAMESIZE(lf)))), |  | ||||||
|        "name"); |  | ||||||
|   printf("1:"); |  | ||||||
|   ShowExtras(ZIP_LFILE_EXTRA(lf), ZIP_LFILE_EXTRASIZE(lf), true); |  | ||||||
|   printf("2:"); |  | ||||||
|   disassemblehex(ZIP_LFILE_CONTENT(lf), ZIP_LFILE_COMPRESSEDSIZE(lf), stdout); |  | ||||||
|   printf("3:\n"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void DisassembleZip(const char *path, uint8_t *p, size_t n) { |  | ||||||
|   size_t i, records; |  | ||||||
|   uint8_t *eocd, *cdir, *cf, *lf; |  | ||||||
|   CHECK_NOTNULL((eocd = GetZipEocd(p, n, 0))); |  | ||||||
|   records = GetZipCdirRecords(eocd); |  | ||||||
|   cdir = p + GetZipCdirOffset(eocd); |  | ||||||
|   for (i = 0, cf = cdir; i < records; ++i, cf += ZIP_CFILE_HDRSIZE(cf)) { |  | ||||||
|     CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(cf)); |  | ||||||
|     lf = p + GetZipCfileOffset(cf); |  | ||||||
|     CHECK_EQ(kZipLfileHdrMagic, ZIP_LFILE_MAGIC(lf)); |  | ||||||
|     ShowLocalFileHeader(lf, i); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int fd; |  | ||||||
|   uint8_t *map; |  | ||||||
|   struct stat st; |  | ||||||
|   ShowCrashReports(); |  | ||||||
|   CHECK_EQ(2, argc); |  | ||||||
|   CHECK_NE(-1, (fd = open(argv[1], O_RDONLY))); |  | ||||||
|   CHECK_NE(-1, fstat(fd, &st)); |  | ||||||
|   CHECK_GE(st.st_size, kZipCdirHdrMinSize); |  | ||||||
|   CHECK_NE(MAP_FAILED, |  | ||||||
|            (map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0))); |  | ||||||
|   DisassembleZip(argv[1], map, st.st_size); |  | ||||||
|   CHECK_NE(-1, munmap(map, st.st_size)); |  | ||||||
|   CHECK_NE(-1, close(fd)); |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,4 +1,3 @@ | ||||||
| (require 'ctest-mode) |  | ||||||
| (require 'ld-script) | (require 'ld-script) | ||||||
| (require 'optinfo-mode) | (require 'optinfo-mode) | ||||||
| (require 'protobuf-mode) | (require 'protobuf-mode) | ||||||
|  |  | ||||||
|  | @ -1,115 +0,0 @@ | ||||||
| (defconst ctest-operators |  | ||||||
|   '("+" |  | ||||||
|     "-" |  | ||||||
|     "*" |  | ||||||
|     "/" |  | ||||||
|     "%" |  | ||||||
|     "//" |  | ||||||
|     "**" |  | ||||||
|     "~" |  | ||||||
|     "^" |  | ||||||
|     "|" |  | ||||||
|     "&" |  | ||||||
|     ">>" |  | ||||||
|     "<<" |  | ||||||
|     "!" |  | ||||||
|     "||" |  | ||||||
|     "&&" |  | ||||||
|     "=" |  | ||||||
|     "!=" |  | ||||||
|     "<" |  | ||||||
|     ">" |  | ||||||
|     "<=" |  | ||||||
|     ">=")) |  | ||||||
| 
 |  | ||||||
| (defconst ctest-consts |  | ||||||
|   '("false" |  | ||||||
|     "true" |  | ||||||
|     "e" |  | ||||||
|     "pi" |  | ||||||
|     "epsilon" |  | ||||||
|     "inf" |  | ||||||
|     "nan" |  | ||||||
|     "l2t" |  | ||||||
|     "lg2" |  | ||||||
|     "ln2" |  | ||||||
|     "l2e")) |  | ||||||
| 
 |  | ||||||
| (defconst ctest-builtins |  | ||||||
|   '("emit" |  | ||||||
|     "exit" |  | ||||||
|     "meminfo" |  | ||||||
|     "isnan" |  | ||||||
|     "isinf" |  | ||||||
|     "signbit" |  | ||||||
|     "isfinite" |  | ||||||
|     "isnormal" |  | ||||||
|     "fpclassify")) |  | ||||||
| 
 |  | ||||||
| (defconst ctest-functions |  | ||||||
|   '("emit" |  | ||||||
|     "cr" |  | ||||||
|     "key" |  | ||||||
|     "dup" |  | ||||||
|     "swap" |  | ||||||
|     "over" |  | ||||||
|     "drop" |  | ||||||
|     "expect" |  | ||||||
|     "assert" |  | ||||||
|     "abs" |  | ||||||
|     "min" |  | ||||||
|     "max")) |  | ||||||
| 
 |  | ||||||
| (defconst ctest-functions-libm |  | ||||||
|   '("mod" |  | ||||||
|     "rem" |  | ||||||
|     "gray" |  | ||||||
|     "ungray" |  | ||||||
|     "popcnt" |  | ||||||
|     "sqrt" |  | ||||||
|     "exp" |  | ||||||
|     "exp2" |  | ||||||
|     "exp10" |  | ||||||
|     "ldexp" |  | ||||||
|     "log" |  | ||||||
|     "log2" |  | ||||||
|     "log10" |  | ||||||
|     "sin" |  | ||||||
|     "cos" |  | ||||||
|     "tan" |  | ||||||
|     "asin" |  | ||||||
|     "acos" |  | ||||||
|     "atan" |  | ||||||
|     "atan2" |  | ||||||
|     "round" |  | ||||||
|     "trunc" |  | ||||||
|     "rint" |  | ||||||
|     "nearbyint" |  | ||||||
|     "ceil" |  | ||||||
|     "floor" |  | ||||||
|     "rand" |  | ||||||
|     "rand64")) |  | ||||||
| 
 |  | ||||||
| (defun ctest--make-regex (words) |  | ||||||
|   (concat "\\_<" (regexp-opt words) "\\_>")) |  | ||||||
| 
 |  | ||||||
| (defconst ctest-highlights |  | ||||||
|   `(("\\(#.*\\)$" 1 font-lock-comment-face) |  | ||||||
|     ("\\b0\\([xX]\\)[[:xdigit:]]+\\([ulUL]*\\)\\b" |  | ||||||
|      (1 font-lock-constant-face) |  | ||||||
|      (2 font-lock-constant-face)) |  | ||||||
|     ("\\b0\\([bB]\\)[01]+\\([ulUL]*\\)\\b" |  | ||||||
|      (1 font-lock-constant-face) |  | ||||||
|      (2 font-lock-constant-face)) |  | ||||||
|     (,(concat "\\_<" (regexp-opt ctest-consts) "\\_>") . |  | ||||||
|      font-lock-constant-face) |  | ||||||
|     (,(concat "\\_<" (regexp-opt ctest-builtins) "\\_>") . |  | ||||||
|      font-lock-builtin-face))) |  | ||||||
| 
 |  | ||||||
| (define-derived-mode ctest-mode fundamental-mode "CALCULATOR.COM" |  | ||||||
|   "Major mode for editing CALCULATOR.COM smoke tests." |  | ||||||
|   (setq font-lock-defaults '(ctest-highlights))) |  | ||||||
| 
 |  | ||||||
| (add-to-list 'auto-mode-alist '("\\.ctest$" . ctest-mode)) |  | ||||||
| 
 |  | ||||||
| (provide 'ctest-mode) |  | ||||||
|  | @ -1,315 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/fmt/conv.h" |  | ||||||
| #include "libc/fmt/fmt.h" |  | ||||||
| #include "libc/intrin/safemacros.internal.h" |  | ||||||
| #include "libc/limits.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/log/log.h" |  | ||||||
| #include "libc/macros.internal.h" |  | ||||||
| #include "libc/math.h" |  | ||||||
| #include "libc/mem/gc.internal.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/lcg.internal.h" |  | ||||||
| #include "libc/stdio/rand.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/exit.h" |  | ||||||
| #include "libc/x/x.h" |  | ||||||
| #include "third_party/gdtoa/gdtoa.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| #include "tool/viz/lib/formatstringtable.h" |  | ||||||
| 
 |  | ||||||
| typedef double (*round_f)(double); |  | ||||||
| typedef unsigned long (*rand_f)(void); |  | ||||||
| 
 |  | ||||||
| struct Range { |  | ||||||
|   long double a; |  | ||||||
|   long double b; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| short xn_ = 8; |  | ||||||
| short yn_ = 8; |  | ||||||
| double digs_ = 6; |  | ||||||
| rand_f rand_; |  | ||||||
| round_f rounder_; |  | ||||||
| const char *path_ = "-"; |  | ||||||
| const char *name_ = "M"; |  | ||||||
| const char *type_ = "float"; |  | ||||||
| struct Range r1_ = {LONG_MIN, LONG_MAX}; |  | ||||||
| struct Range r2_ = {0, 1}; |  | ||||||
| StringTableFormatter *formatter_ = FormatStringTableAsCode; |  | ||||||
| 
 |  | ||||||
| static wontreturn void PrintUsage(int rc, FILE *f) { |  | ||||||
|   fprintf(f, "Usage: %s%s", program_invocation_name, "\
 |  | ||||||
|  [FLAGS] [FILE]\n\ |  | ||||||
| \n\ |  | ||||||
| Flags:\n\ |  | ||||||
|   -u         unsigned\n\ |  | ||||||
|   -c         char\n\ |  | ||||||
|   -s         short\n\ |  | ||||||
|   -i         int\n\ |  | ||||||
|   -l         long\n\ |  | ||||||
|   -d         double\n\ |  | ||||||
|   -b         bytes [-uc]\n\ |  | ||||||
|   -g         non-deterministic rng\n\ |  | ||||||
|   -S         output assembly\n\ |  | ||||||
|   -W         output whitespace\n\ |  | ||||||
|   -o PATH    output path\n\ |  | ||||||
|   -x FLEX\n\ |  | ||||||
|   -w FLEX    width\n\ |  | ||||||
|   -y FLEX\n\ |  | ||||||
|   -h FLEX    height\n\ |  | ||||||
|   -N NAME    name\n\ |  | ||||||
|   -T NAME    type name\n\ |  | ||||||
|   -A FLEX    min value\n\ |  | ||||||
|   -B FLEX    max value\n\ |  | ||||||
|   -R FUNC    round function for indexing\n\ |  | ||||||
|   -D FLEX    decimal digits to printout\n\ |  | ||||||
|   -v         increases verbosity\n\ |  | ||||||
|   -?         shows this information\n\ |  | ||||||
| \n"); |  | ||||||
|   exit(rc); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool StringEquals(const char *a, const char *b) { |  | ||||||
|   return strcasecmp(a, b) == 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static wontreturn void ShowInvalidArg(const char *name, const char *s, |  | ||||||
|                                       const char *type) { |  | ||||||
|   fprintf(stderr, "error: invalid %s %s: %s\n", type, name, s); |  | ||||||
|   exit(EXIT_FAILURE); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static double ParseFlexidecimalOrDie(const char *name, const char *s, |  | ||||||
|                                      double min, double max) { |  | ||||||
|   double x; |  | ||||||
|   s = firstnonnull(s, "NULL"); |  | ||||||
|   if (strchr(s, '.') || strchr(s, 'e')) { |  | ||||||
|     x = strtod(s, NULL); |  | ||||||
|   } else { |  | ||||||
|     x = strtol(s, NULL, 0); |  | ||||||
|   } |  | ||||||
|   if (min <= x && x <= max) { |  | ||||||
|     return x; |  | ||||||
|   } else { |  | ||||||
|     ShowInvalidArg(name, s, "flexidecimal"); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static round_f ParseRoundingFunctionOrDie(const char *s) { |  | ||||||
|   if (isempty(s) || StringEquals(s, "none") || StringEquals(s, "null")) { |  | ||||||
|     return NULL; |  | ||||||
|   } else if (StringEquals(s, "round")) { |  | ||||||
|     return round; |  | ||||||
|   } else if (StringEquals(s, "rint")) { |  | ||||||
|     return rint; |  | ||||||
|   } else if (StringEquals(s, "nearbyint")) { |  | ||||||
|     return nearbyint; |  | ||||||
|   } else if (StringEquals(s, "trunc")) { |  | ||||||
|     return trunc; |  | ||||||
|   } else if (StringEquals(s, "floor")) { |  | ||||||
|     return floor; |  | ||||||
|   } else if (StringEquals(s, "ceil")) { |  | ||||||
|     return ceil; |  | ||||||
|   } else { |  | ||||||
|     ShowInvalidArg("round", s, "func"); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void ConfigureIntegralRange(const char *type, long min, long max) { |  | ||||||
|   type_ = type; |  | ||||||
|   r1_.a = min; |  | ||||||
|   r1_.b = max; |  | ||||||
|   r2_.a = min; |  | ||||||
|   r2_.b = max; |  | ||||||
|   if (!rounder_) rounder_ = round; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GetOpts(int argc, char *argv[]) { |  | ||||||
|   int opt; |  | ||||||
|   bool want_unsigned, want_char, want_short, want_int, want_long, want_double; |  | ||||||
|   want_unsigned = false; |  | ||||||
|   want_char = false; |  | ||||||
|   want_short = false; |  | ||||||
|   want_int = false; |  | ||||||
|   want_long = false; |  | ||||||
|   want_double = false; |  | ||||||
|   if (argc == 2 && |  | ||||||
|       (StringEquals(argv[1], "--help") || StringEquals(argv[1], "-help"))) { |  | ||||||
|     PrintUsage(EXIT_SUCCESS, stdout); |  | ||||||
|   } |  | ||||||
|   while ((opt = getopt(argc, argv, "?vubcsildgSWo:x:w:y:h:N:A:B:C:E:T:R:D:")) != |  | ||||||
|          -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case 'b': |  | ||||||
|         want_unsigned = true; |  | ||||||
|         want_char = true; |  | ||||||
|         break; |  | ||||||
|       case 'u': |  | ||||||
|         want_unsigned = true; |  | ||||||
|         break; |  | ||||||
|       case 'c': |  | ||||||
|         want_char = true; |  | ||||||
|         break; |  | ||||||
|       case 's': |  | ||||||
|         want_short = true; |  | ||||||
|         break; |  | ||||||
|       case 'i': |  | ||||||
|         want_int = true; |  | ||||||
|         break; |  | ||||||
|       case 'l': |  | ||||||
|         want_long = true; |  | ||||||
|         break; |  | ||||||
|       case 'd': |  | ||||||
|         want_double = true; |  | ||||||
|         break; |  | ||||||
|       case 'g': |  | ||||||
|         rand_ = _rand64; |  | ||||||
|         break; |  | ||||||
|       case 'N': |  | ||||||
|         name_ = optarg; |  | ||||||
|         break; |  | ||||||
|       case 'o': |  | ||||||
|         path_ = optarg; |  | ||||||
|         break; |  | ||||||
|       case 'S': |  | ||||||
|         formatter_ = FormatStringTableAsAssembly; |  | ||||||
|         break; |  | ||||||
|       case 'W': |  | ||||||
|         formatter_ = FormatStringTableBasic; |  | ||||||
|         break; |  | ||||||
|       case 't': |  | ||||||
|         type_ = optarg; |  | ||||||
|         break; |  | ||||||
|       case 'x': |  | ||||||
|       case 'w': |  | ||||||
|         xn_ = ParseFlexidecimalOrDie("width", optarg, 1, SHRT_MAX); |  | ||||||
|         break; |  | ||||||
|       case 'y': |  | ||||||
|       case 'h': |  | ||||||
|         yn_ = ParseFlexidecimalOrDie("height", optarg, 1, SHRT_MAX); |  | ||||||
|         break; |  | ||||||
|       case 'D': |  | ||||||
|         digs_ = ParseFlexidecimalOrDie("digs", optarg, 0, 15.95); |  | ||||||
|         break; |  | ||||||
|       case 'r': |  | ||||||
|         rounder_ = ParseRoundingFunctionOrDie(optarg); |  | ||||||
|         break; |  | ||||||
|       case 'A': |  | ||||||
|         r1_.a = ParseFlexidecimalOrDie("r1_.a", optarg, INT_MIN, INT_MAX); |  | ||||||
|         break; |  | ||||||
|       case 'B': |  | ||||||
|         r1_.b = ParseFlexidecimalOrDie("r1_.b", optarg, INT_MIN, INT_MAX); |  | ||||||
|         break; |  | ||||||
|       case 'C': |  | ||||||
|         r2_.a = ParseFlexidecimalOrDie("r2_.a", optarg, INT_MIN, INT_MAX); |  | ||||||
|         break; |  | ||||||
|       case 'E': |  | ||||||
|         r2_.b = ParseFlexidecimalOrDie("r2_.b", optarg, INT_MIN, INT_MAX); |  | ||||||
|         break; |  | ||||||
|       case '?': |  | ||||||
|         PrintUsage(EXIT_SUCCESS, stdout); |  | ||||||
|       default: |  | ||||||
|         PrintUsage(EX_USAGE, stderr); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (want_unsigned && want_char) { |  | ||||||
|     ConfigureIntegralRange("unsigned char", 0, 255); |  | ||||||
|   } else if (want_char) { |  | ||||||
|     ConfigureIntegralRange("signed char", -128, 127); |  | ||||||
|   } else if (want_unsigned && want_short) { |  | ||||||
|     ConfigureIntegralRange("unsigned short", USHRT_MIN, USHRT_MAX); |  | ||||||
|   } else if (want_short) { |  | ||||||
|     ConfigureIntegralRange("short", SHRT_MIN, SHRT_MAX); |  | ||||||
|   } else if (want_unsigned && want_int) { |  | ||||||
|     ConfigureIntegralRange("unsigned", UINT_MIN, UINT_MAX); |  | ||||||
|   } else if (want_int) { |  | ||||||
|     ConfigureIntegralRange("int", INT_MIN, INT_MAX); |  | ||||||
|   } else if (want_unsigned && want_long) { |  | ||||||
|     ConfigureIntegralRange("unsigned long", ULONG_MIN, ULONG_MAX); |  | ||||||
|   } else if (want_long) { |  | ||||||
|     ConfigureIntegralRange("long", LONG_MIN, LONG_MAX); |  | ||||||
|   } else if (want_double) { |  | ||||||
|     type_ = "double"; |  | ||||||
|     r1_.a = LONG_MIN; |  | ||||||
|     r1_.b = LONG_MAX; |  | ||||||
|     digs_ = 19; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void *SetRandom(long n, long p[n]) { |  | ||||||
|   long i; |  | ||||||
|   uint64_t r; |  | ||||||
|   if (rand_) { |  | ||||||
|     for (r = 1, i = 0; i < n; ++i) { |  | ||||||
|       p[i] = rand_(); |  | ||||||
|     } |  | ||||||
|   } else { |  | ||||||
|     for (r = 1, i = 0; i < n; ++i) { |  | ||||||
|       p[i] = KnuthLinearCongruentialGenerator(&r) >> 32 | |  | ||||||
|              KnuthLinearCongruentialGenerator(&r) >> 32 << 32; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return p; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static long double ConvertRange(long double x, long double a, long double b, |  | ||||||
|                                 long double c, long double d) { |  | ||||||
|   return (d - c) / (b - a) * (x - a) + c; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static double Compand(long x, double a, double b, double c, double d) { |  | ||||||
|   return ConvertRange(ConvertRange(x, LONG_MIN, LONG_MAX, a, b), a, b, c, d); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void GenerateMatrixImpl(long I[yn_][xn_], double M[yn_][xn_], FILE *f) { |  | ||||||
|   long y, x; |  | ||||||
|   for (y = 0; y < yn_; ++y) { |  | ||||||
|     for (x = 0; x < xn_; ++x) { |  | ||||||
|       M[y][x] = Compand(I[y][x], r1_.a, r1_.b, r2_.a, r2_.b); |  | ||||||
|     } |  | ||||||
|     if (rounder_) { |  | ||||||
|       for (x = 0; x < xn_; ++x) { |  | ||||||
|         M[y][x] = rounder_(M[y][x]); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   FormatMatrixDouble(yn_, xn_, M, fputs, f, formatter_, type_, name_, NULL, |  | ||||||
|                      digs_, round); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GenerateMatrix(FILE *f) { |  | ||||||
|   GenerateMatrixImpl(SetRandom(yn_ * xn_, gc(calloc(yn_ * xn_, sizeof(long)))), |  | ||||||
|                      gc(calloc(yn_ * xn_, sizeof(double))), f); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int i; |  | ||||||
|   FILE *f; |  | ||||||
|   ShowCrashReports(); |  | ||||||
|   GetOpts(argc, argv); |  | ||||||
|   CHECK_NOTNULL((f = fopen(path_, "w"))); |  | ||||||
|   if (optind < argc) FATALF("TODO(jart): support input files"); |  | ||||||
|   GenerateMatrix(f); |  | ||||||
|   return fclose(f); |  | ||||||
| } |  | ||||||
|  | @ -1,116 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/log/check.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/exit.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| 
 |  | ||||||
| static FILE *fi_, *fo_; |  | ||||||
| static char *inpath_, *outpath_; |  | ||||||
| 
 |  | ||||||
| wontreturn void usage(int rc, FILE *f) { |  | ||||||
|   fprintf(f, "%s%s%s\n", "Usage: ", program_invocation_name, |  | ||||||
|           " [-o FILE] [FILE...]\n"); |  | ||||||
|   exit(rc); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void getopts(int *argc, char *argv[]) { |  | ||||||
|   int opt; |  | ||||||
|   outpath_ = "-"; |  | ||||||
|   while ((opt = getopt(*argc, argv, "?ho:")) != -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case 'o': |  | ||||||
|         outpath_ = optarg; |  | ||||||
|         break; |  | ||||||
|       case '?': |  | ||||||
|       case 'h': |  | ||||||
|         usage(EXIT_SUCCESS, stdout); |  | ||||||
|       default: |  | ||||||
|         usage(EX_USAGE, stderr); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (optind == *argc) { |  | ||||||
|     argv[(*argc)++] = "-"; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void processfile(void) { |  | ||||||
|   wint_t wc; |  | ||||||
|   while ((wc = fgetwc(fi_)) != -1) { |  | ||||||
|     switch (wc) { |  | ||||||
|       case L'█': |  | ||||||
|         wc = L' '; |  | ||||||
|         break; |  | ||||||
|       case L'▓': |  | ||||||
|         wc = L'░'; |  | ||||||
|         break; |  | ||||||
|       case L'▒': |  | ||||||
|         wc = L'▒'; |  | ||||||
|         break; |  | ||||||
|       case L'░': |  | ||||||
|         wc = L'▓'; |  | ||||||
|         break; |  | ||||||
|         /* █ */ |  | ||||||
|       case L'▐': |  | ||||||
|         wc = L'▌'; |  | ||||||
|         break; |  | ||||||
|       case L'▌': |  | ||||||
|         wc = L'▐'; |  | ||||||
|         break; |  | ||||||
|       case L'▀': |  | ||||||
|         wc = L'▄'; |  | ||||||
|         break; |  | ||||||
|       case L'▄': |  | ||||||
|         wc = L'▀'; |  | ||||||
|         break; |  | ||||||
|       case L'☺': |  | ||||||
|         wc = L'☻'; |  | ||||||
|         break; |  | ||||||
|       case L'☻': |  | ||||||
|         wc = L'☺'; |  | ||||||
|         break; |  | ||||||
|       case L'○': |  | ||||||
|         wc = L'◙'; |  | ||||||
|         break; |  | ||||||
|       case L'◙': |  | ||||||
|         wc = L'○'; |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     fputwc(wc, fo_); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   size_t i; |  | ||||||
|   getopts(&argc, argv); |  | ||||||
|   CHECK_NOTNULL((fo_ = fopen(outpath_, "w"))); |  | ||||||
|   for (i = optind; i < argc; ++i) { |  | ||||||
|     CHECK_NOTNULL((fi_ = fopen((inpath_ = argv[i]), "r"))); |  | ||||||
|     processfile(); |  | ||||||
|     CHECK_NE(-1, fclose(fi_)); |  | ||||||
|     fi_ = 0; |  | ||||||
|   } |  | ||||||
|   CHECK_NE(-1, fclose(fo_)); |  | ||||||
|   fo_ = 0; |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,642 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "dsp/core/c1331.h" |  | ||||||
| #include "dsp/core/c161.h" |  | ||||||
| #include "dsp/core/core.h" |  | ||||||
| #include "dsp/scale/scale.h" |  | ||||||
| #include "libc/assert.h" |  | ||||||
| #include "libc/calls/calls.h" |  | ||||||
| #include "libc/calls/struct/stat.h" |  | ||||||
| #include "libc/fmt/conv.h" |  | ||||||
| #include "libc/limits.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/log/log.h" |  | ||||||
| #include "libc/macros.internal.h" |  | ||||||
| #include "libc/math.h" |  | ||||||
| #include "libc/mem/gc.internal.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/rand.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.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/testlib/testlib.h" |  | ||||||
| #include "libc/x/x.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| #include "third_party/stb/stb_image.h" |  | ||||||
| #include "tool/viz/lib/bilinearscale.h" |  | ||||||
| #include "tool/viz/lib/graphic.h" |  | ||||||
| 
 |  | ||||||
| #define LONG          long |  | ||||||
| #define CHAR          char |  | ||||||
| #define CLAMP(X)      MIN(255, MAX(0, X)) |  | ||||||
| #define C13(A, B)     (((A) + 3 * (B) + 2) >> 2) |  | ||||||
| #define LERP(X, Y, P) ((X) + (((P) * ((Y) - (X))) >> 8)) |  | ||||||
| 
 |  | ||||||
| static double r_; |  | ||||||
| 
 |  | ||||||
| static unsigned char ChessBoard(unsigned y, unsigned x, unsigned char a, |  | ||||||
|                                 unsigned char b) { |  | ||||||
|   return !((y ^ x) & (1u << 2)) ? a : b; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned char AlphaBackground(unsigned y, unsigned x) { |  | ||||||
|   return ChessBoard(y, x, 255, 200); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned char OutOfBoundsBackground(unsigned y, unsigned x) { |  | ||||||
|   return ChessBoard(y, x, 40, 80); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned char Opacify(CHAR w, const unsigned char P[1u << w][1u << w], |  | ||||||
|                              const unsigned char A[1u << w][1u << w], LONG yn, |  | ||||||
|                              LONG xn, long y, long x) { |  | ||||||
|   if ((0 <= y && y < yn) && (0 <= x && x < xn)) { |  | ||||||
|     return LERP(AlphaBackground(y, x), P[y][x], A[y][x]); |  | ||||||
|   } else { |  | ||||||
|     return OutOfBoundsBackground(y, x); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void PrintImage(CHAR w, unsigned char R[1u << w][1u << w], |  | ||||||
|                        unsigned char G[1u << w][1u << w], |  | ||||||
|                        unsigned char B[1u << w][1u << w], |  | ||||||
|                        unsigned char A[1u << w][1u << w], LONG yn, LONG xn) { |  | ||||||
|   bool didhalfy; |  | ||||||
|   long y, x; |  | ||||||
|   didhalfy = false; |  | ||||||
|   for (y = 0; y < yn; y += 2) { |  | ||||||
|     if (y) printf("\e[0m\n"); |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       printf("\e[48;2;%d;%d;%d;38;2;%d;%d;%dm▄", |  | ||||||
|              Opacify(w, R, A, yn, xn, y + 0, x), |  | ||||||
|              Opacify(w, G, A, yn, xn, y + 0, x), |  | ||||||
|              Opacify(w, B, A, yn, xn, y + 0, x), |  | ||||||
|              Opacify(w, R, A, yn, xn, y + 1, x), |  | ||||||
|              Opacify(w, G, A, yn, xn, y + 1, x), |  | ||||||
|              Opacify(w, B, A, yn, xn, y + 1, x)); |  | ||||||
|     } |  | ||||||
|     if (y == 0) { |  | ||||||
|       printf("\e[0m‾0"); |  | ||||||
|     } else if (yn / 2 <= y && y <= yn / 2 + 1 && !didhalfy) { |  | ||||||
|       printf("\e[0m‾%s%s", "yn/2", y % 2 ? "+1" : ""); |  | ||||||
|       didhalfy = true; |  | ||||||
|     } else if (y + 1 == yn / 2 && !didhalfy) { |  | ||||||
|       printf("\e[0m⎯yn/2"); |  | ||||||
|       didhalfy = true; |  | ||||||
|     } else if (y + 1 == yn) { |  | ||||||
|       printf("\e[0m⎯yn"); |  | ||||||
|     } else if (y + 2 == yn) { |  | ||||||
|       printf("\e[0m_yn"); |  | ||||||
|     } else if (!(y % 10)) { |  | ||||||
|       printf("\e[0m‾%,u", y); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   printf("\e[0m\n"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void DeblinterlaceRgba(CHAR w, unsigned char R[1u << w][1u << w], |  | ||||||
|                               unsigned char G[1u << w][1u << w], |  | ||||||
|                               unsigned char B[1u << w][1u << w], |  | ||||||
|                               unsigned char A[1u << w][1u << w], LONG yn, |  | ||||||
|                               LONG xn, const unsigned char src[yn][xn][4]) { |  | ||||||
|   long y, x; |  | ||||||
|   for (y = 0; y < yn; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       R[y][x] = src[y][x][0]; |  | ||||||
|       G[y][x] = src[y][x][1]; |  | ||||||
|       B[y][x] = src[y][x][2]; |  | ||||||
|       A[y][x] = src[y][x][3]; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void SharpenX(CHAR w, unsigned char dst[1u << w][1u << w], |  | ||||||
|                      const unsigned char src[1u << w][1u << w], char yw, |  | ||||||
|                      char xw) { |  | ||||||
|   int y, x; |  | ||||||
|   for (y = 0; y < (1u << yw); ++y) { |  | ||||||
|     for (x = 0; x < (1u << xw); ++x) { |  | ||||||
|       dst[y][x] = C161(src[y][MAX(0, x - 1)], src[y][x], |  | ||||||
|                        src[y][MIN((1u << xw) - 1, x + 1)]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void SharpenY(CHAR w, unsigned char dst[1u << w][1u << w], |  | ||||||
|                      const unsigned char src[1u << w][1u << w], char yw, |  | ||||||
|                      char xw) { |  | ||||||
|   int y, x; |  | ||||||
|   for (y = 0; y < (1u << yw); ++y) { |  | ||||||
|     for (x = 0; x < (1u << xw); ++x) { |  | ||||||
|       dst[y][x] = C161(src[MAX(0, y - 1)][x], src[y][x], |  | ||||||
|                        src[MIN((1u << yw) - 1, y + 1)][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void UpscaleX(CHAR w, unsigned char img[1u << w][1u << w], char yw, |  | ||||||
|                      char xw) { |  | ||||||
|   long y, x; |  | ||||||
|   for (y = (1u << yw); y--;) { |  | ||||||
|     for (x = (1u << xw); --x;) { |  | ||||||
|       img[y][x] = |  | ||||||
|           C13(img[y][MIN(((1u << xw) >> 1) - 1, (x >> 1) - 1 + (x & 1) * 2)], |  | ||||||
|               img[y][x >> 1]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void UpscaleY(CHAR w, unsigned char img[1u << w][1u << w], char yw, |  | ||||||
|                      char xw) { |  | ||||||
|   long y, x; |  | ||||||
|   for (y = (1u << yw); --y;) { |  | ||||||
|     for (x = (1u << xw); x--;) { |  | ||||||
|       img[y][x] = |  | ||||||
|           C13(img[MIN(((1u << yw) >> 1) - 1, (y >> 1) - 1 + (y & 1) * 2)][x], |  | ||||||
|               img[y >> 1][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void Upscale(CHAR w, unsigned char img[1u << w][1u << w], |  | ||||||
|                     unsigned char tmp[1u << w][1u << w], char yw, char xw) { |  | ||||||
|   UpscaleY(w, img, yw, xw - 1); |  | ||||||
|   SharpenY(w, tmp, img, yw, xw - 1); |  | ||||||
|   UpscaleX(w, tmp, yw, xw); |  | ||||||
|   SharpenX(w, img, tmp, yw, xw); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
| static void *MagikarpY(CHAR w, unsigned char p[1u << w][1u << w], char yw, |  | ||||||
|                        char xw) { |  | ||||||
|   long y, x, yn, xn, ym; |  | ||||||
|   unsigned char(*t)[(1u << w) + 2][1u << w]; |  | ||||||
|   t = memalign(64, ((1u << w) + 2) * (1u << w)); |  | ||||||
|   bzero(t, ((1u << w) + 2) * (1u << w)); |  | ||||||
|   yn = 1u << yw; |  | ||||||
|   xn = 1u << xw; |  | ||||||
|   ym = yn >> 1; |  | ||||||
|   for (y = 0; y < ym; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       (*t)[y + 1][x] = |  | ||||||
|           C1331(y ? p[(y << 1) - 1][x] : 0, p[y << 1][x], p[(y << 1) + 1][x], |  | ||||||
|                 p[MIN(yn - 1, (y << 1) + 2)][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   for (y = 0; y < ym; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       p[y][x] = |  | ||||||
|           C161((*t)[y + 1 - 1][x], (*t)[y + 1 + 0][x], (*t)[y + 1 + 1][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   free(t); |  | ||||||
|   return p; |  | ||||||
| } |  | ||||||
| static void *MagikarpX(CHAR w, unsigned char p[1u << w][1u << w], char yw, |  | ||||||
|                        char xw) { |  | ||||||
|   int y, x; |  | ||||||
|   LONG yn, xn, xm; |  | ||||||
|   yn = 1u << yw; |  | ||||||
|   xn = 1u << xw; |  | ||||||
|   xm = xn >> 1; |  | ||||||
|   for (x = 0; x < xm; ++x) { |  | ||||||
|     for (y = 0; y < yn; ++y) { |  | ||||||
|       p[y][(xn - xm - 1) + (xm - x - 1)] = |  | ||||||
|           C1331(p[y][MAX(00 + 0, xn - (x << 1) - 1 + (xn & 1) - 1)], |  | ||||||
|                 p[y][MIN(xn - 1, xn - (x << 1) - 1 + (xn & 1) + 0)], |  | ||||||
|                 p[y][MIN(xn - 1, xn - (x << 1) - 1 + (xn & 1) + 1)], |  | ||||||
|                 p[y][MIN(xn - 1, xn - (x << 1) - 1 + (xn & 1) + 2)]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   for (x = 0; x < xm; ++x) { |  | ||||||
|     for (y = 0; y < yn; ++y) { |  | ||||||
|       p[y][x] = C161(p[y][MAX(xn - 1 - xm, xn - xm - 1 + x - 1)], |  | ||||||
|                      p[y][MIN(xn - 1 - 00, xn - xm - 1 + x + 0)], |  | ||||||
|                      p[y][MIN(xn - 1 - 00, xn - xm - 1 + x + 1)]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return p; |  | ||||||
| } |  | ||||||
| static void ProcessImageVerbatim(LONG yn, LONG xn, |  | ||||||
|                                  unsigned char img[yn][xn][4]) { |  | ||||||
|   CHAR w; |  | ||||||
|   void *R, *G, *B, *A; |  | ||||||
|   w = _roundup2log(MAX(yn, xn)); |  | ||||||
|   R = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   G = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   B = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   A = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   DeblinterlaceRgba(w, R, G, B, A, yn, xn, img); |  | ||||||
|   PrintImage(w, R, G, B, A, yn, xn); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| static void ProcessImageDouble(LONG yn, LONG xn, unsigned char img[yn][xn][4]) { |  | ||||||
|   CHAR w; |  | ||||||
|   void *t, *R, *G, *B, *A; |  | ||||||
|   w = _roundup2log(MAX(yn, xn)) + 1; |  | ||||||
|   t = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   R = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   G = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   B = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   A = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   DeblinterlaceRgba(w, R, G, B, A, yn, xn, img); |  | ||||||
|   Upscale(w, R, t, w, w); |  | ||||||
|   Upscale(w, G, t, w, w); |  | ||||||
|   Upscale(w, B, t, w, w); |  | ||||||
|   Upscale(w, A, t, w, w); |  | ||||||
|   free(t); |  | ||||||
|   PrintImage(w, R, G, B, A, yn * 2, xn * 2); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| static void ProcessImageHalf(LONG yn, LONG xn, unsigned char img[yn][xn][4]) { |  | ||||||
|   CHAR w; |  | ||||||
|   void *R, *G, *B, *A; |  | ||||||
|   w = _roundup2log(MAX(yn, xn)); |  | ||||||
|   R = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   G = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   B = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   A = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   DeblinterlaceRgba(w, R, G, B, A, yn, xn, img); |  | ||||||
|   MagikarpY(w, R, w, w); |  | ||||||
|   MagikarpY(w, G, w, w); |  | ||||||
|   MagikarpY(w, B, w, w); |  | ||||||
|   MagikarpY(w, A, w, w); |  | ||||||
|   MagikarpX(w, R, w - 1, w); |  | ||||||
|   MagikarpX(w, G, w - 1, w); |  | ||||||
|   MagikarpX(w, B, w - 1, w); |  | ||||||
|   MagikarpX(w, A, w - 1, w); |  | ||||||
|   PrintImage(w, R, G, B, A, yn >> 1, xn >> 1); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| static void ProcessImageHalfY(LONG yn, LONG xn, unsigned char img[yn][xn][4]) { |  | ||||||
|   CHAR w; |  | ||||||
|   void *R, *G, *B, *A; |  | ||||||
|   w = _roundup2log(MAX(yn, xn)); |  | ||||||
|   R = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   G = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   B = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   A = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   DeblinterlaceRgba(w, R, G, B, A, yn, xn, img); |  | ||||||
|   MagikarpY(w, R, w, w); |  | ||||||
|   MagikarpY(w, G, w, w); |  | ||||||
|   MagikarpY(w, B, w, w); |  | ||||||
|   MagikarpY(w, A, w, w); |  | ||||||
|   PrintImage(w, R, G, B, A, yn >> 1, xn); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| static void ProcessImageHalfLanczos(LONG yn, LONG xn, |  | ||||||
|                                     unsigned char img[yn][xn][4]) { |  | ||||||
|   CHAR w; |  | ||||||
|   void *t, *R, *G, *B, *A; |  | ||||||
|   t = xvalloc((yn >> 1) * (xn >> 1) * 4); |  | ||||||
|   lanczos1b(yn >> 1, xn >> 1, t, yn, xn, &img[0][0][0]); |  | ||||||
|   w = _roundup2log(MAX(yn >> 1, xn >> 1)); |  | ||||||
|   R = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   G = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   B = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   A = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   DeblinterlaceRgba(w, R, G, B, A, yn >> 1, xn >> 1, img); |  | ||||||
|   free(t); |  | ||||||
|   PrintImage(w, R, G, B, A, yn >> 1, xn >> 1); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| static void ProcessImageWash(LONG yn, LONG xn, unsigned char img[yn][xn][4]) { |  | ||||||
|   long w; |  | ||||||
|   void *R, *G, *B, *A, *t; |  | ||||||
|   w = _roundup2log(MAX(yn, xn)) + 1; |  | ||||||
|   t = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   R = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   G = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   B = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   A = xvalloc((1u << w) * (1u << w)); |  | ||||||
|   DeblinterlaceRgba(w, R, G, B, A, yn, xn, img); |  | ||||||
|   Upscale(w, R, t, w, w); |  | ||||||
|   Upscale(w, G, t, w, w); |  | ||||||
|   Upscale(w, B, t, w, w); |  | ||||||
|   Upscale(w, A, t, w, w); |  | ||||||
|   MagikarpY(w, R, w, w); |  | ||||||
|   MagikarpY(w, G, w, w); |  | ||||||
|   MagikarpY(w, B, w, w); |  | ||||||
|   MagikarpY(w, A, w, w); |  | ||||||
|   MagikarpX(w, R, w - 1, w); |  | ||||||
|   MagikarpX(w, G, w - 1, w); |  | ||||||
|   MagikarpX(w, B, w - 1, w); |  | ||||||
|   MagikarpX(w, A, w - 1, w); |  | ||||||
|   free(t); |  | ||||||
|   PrintImage(w, R, G, B, A, yn, xn); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
| static void *MagikarpY(size_t ys, size_t xs, unsigned char p[ys][xs], size_t yn, |  | ||||||
|                        size_t xn) { |  | ||||||
|   int y, x, h, b; |  | ||||||
|   b = yn % 2; |  | ||||||
|   h = yn / 2; |  | ||||||
|   if (b && yn < ys) yn++; |  | ||||||
|   for (y = b; y < h + b; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       p[(yn - h - 1) + (h - y - 1)][x] = |  | ||||||
|           C1331(p[MAX(00 + 0, yn - y * 2 - 1 - 1)][x], |  | ||||||
|                 p[MIN(yn - 1, yn - y * 2 - 1 + 0)][x], |  | ||||||
|                 p[MIN(yn - 1, yn - y * 2 - 1 + 1)][x], |  | ||||||
|                 p[MIN(yn - 1, yn - y * 2 - 1 + 2)][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   for (y = b; y < h + b; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       p[y][x] = C161(p[MAX(yn - 1 - h, yn - h - 1 + y - 1)][x], |  | ||||||
|                      p[MIN(yn - 1 - 0, yn - h - 1 + y + 0)][x], |  | ||||||
|                      p[MIN(yn - 1 - 0, yn - h - 1 + y + 1)][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return p; |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
| static void *MagikarpX(size_t ys, size_t xs, unsigned char p[ys][xs], size_t yn, |  | ||||||
|                        size_t xn) { |  | ||||||
|   int y, x, w, b; |  | ||||||
|   b = xn % 2; |  | ||||||
|   w = xn / 2; |  | ||||||
|   if (b && xn < xs) xn++; |  | ||||||
|   for (x = 0; x < w; ++x) { |  | ||||||
|     for (y = b; y < yn + b; ++y) { |  | ||||||
|       p[y][(xn - w - 1) + (w - x - 1)] = |  | ||||||
|           C1331(p[y][MAX(00 + 0, xn - x * 2 - 1 - 1)], |  | ||||||
|                 p[y][MIN(xn - 1, xn - x * 2 - 1 + 0)], |  | ||||||
|                 p[y][MIN(xn - 1, xn - x * 2 - 1 + 1)], |  | ||||||
|                 p[y][MIN(xn - 1, xn - x * 2 - 1 + 2)]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   for (x = 0; x < w; ++x) { |  | ||||||
|     for (y = b; y < yn + b; ++y) { |  | ||||||
|       p[y][x] = C161(p[y][MAX(xn - 1 - w, xn - w - 1 + x - 1)], |  | ||||||
|                      p[y][MIN(xn - 1 - 0, xn - w - 1 + x + 0)], |  | ||||||
|                      p[y][MIN(xn - 1 - 0, xn - w - 1 + x + 1)]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return p; |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
| static void ProcessImageMagikarpImpl(CHAR sw, |  | ||||||
|                                      unsigned char src[5][1u << sw][1u << sw], |  | ||||||
|                                      LONG syn, LONG sxn, |  | ||||||
|                                      const unsigned char img[syn][sxn][4], |  | ||||||
|                                      LONG dyn, LONG dxn) { |  | ||||||
|   DeblinterlaceRgba2(sw, src, syn, sxn, img); |  | ||||||
|   MagikarpY(sw, src[0], sw, sw); |  | ||||||
|   MagikarpX(sw, src[0], sw - 1, sw); |  | ||||||
|   MagikarpY(sw, src[1], sw, sw); |  | ||||||
|   MagikarpX(sw, src[1], sw - 1, sw); |  | ||||||
|   MagikarpY(sw, src[2], sw, sw); |  | ||||||
|   MagikarpX(sw, src[2], sw - 1, sw); |  | ||||||
|   BilinearScale(sw, src[4], sw, src[3], dyn, dxn, syn, sxn); |  | ||||||
|   memcpy(src[3], src[4], syn * sxn); |  | ||||||
|   PrintImage2(sw, src, dyn, dxn); |  | ||||||
| } |  | ||||||
| static void ProcessImageMagikarp(LONG syn, LONG sxn, |  | ||||||
|                                  unsigned char img[syn][sxn][4]) { |  | ||||||
|   CHAR sw; |  | ||||||
|   LONG dyn, dxn; |  | ||||||
|   dyn = syn >> 1; |  | ||||||
|   dxn = sxn >> 1; |  | ||||||
|   sw = _roundup2log(MAX(syn, sxn)); |  | ||||||
|   ProcessImageMagikarpImpl(sw, gc(xvalloc((1u << sw) * (1u << sw) * 5)), syn, |  | ||||||
|                            sxn, img, dyn, dxn); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
| ******************************************************************************** |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| static unsigned char Opacify2(unsigned yw, unsigned xw, |  | ||||||
|                               const unsigned char P[yw][xw], |  | ||||||
|                               const unsigned char A[yw][xw], unsigned yn, |  | ||||||
|                               unsigned xn, unsigned y, unsigned x) { |  | ||||||
|   if ((0 <= y && y < yn) && (0 <= x && x < xn)) { |  | ||||||
|     return LERP(AlphaBackground(y, x), P[y][x], A[y][x]); |  | ||||||
|   } else { |  | ||||||
|     return OutOfBoundsBackground(y, x); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static dontinline void PrintImage2(unsigned yw, unsigned xw, |  | ||||||
|                                    unsigned char img[4][yw][xw], unsigned yn, |  | ||||||
|                                    unsigned xn) { |  | ||||||
|   bool didhalfy; |  | ||||||
|   unsigned y, x; |  | ||||||
|   didhalfy = false; |  | ||||||
|   for (y = 0; y < yn; y += 2) { |  | ||||||
|     if (y) printf("\e[0m\n"); |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       printf("\e[48;2;%d;%d;%d;38;2;%d;%d;%dm▄", |  | ||||||
|              Opacify2(yw, xw, img[0], img[3], yn, xn, y + 0, x), |  | ||||||
|              Opacify2(yw, xw, img[1], img[3], yn, xn, y + 0, x), |  | ||||||
|              Opacify2(yw, xw, img[2], img[3], yn, xn, y + 0, x), |  | ||||||
|              Opacify2(yw, xw, img[0], img[3], yn, xn, y + 1, x), |  | ||||||
|              Opacify2(yw, xw, img[1], img[3], yn, xn, y + 1, x), |  | ||||||
|              Opacify2(yw, xw, img[2], img[3], yn, xn, y + 1, x)); |  | ||||||
|     } |  | ||||||
|     if (y == 0) { |  | ||||||
|       printf("\e[0m‾0"); |  | ||||||
|     } else if (yn / 2 <= y && y <= yn / 2 + 1 && !didhalfy) { |  | ||||||
|       printf("\e[0m‾%s%s", "yn/2", y % 2 ? "+1" : ""); |  | ||||||
|       didhalfy = true; |  | ||||||
|     } else if (y + 1 == yn / 2 && !didhalfy) { |  | ||||||
|       printf("\e[0m⎯yn/2"); |  | ||||||
|       didhalfy = true; |  | ||||||
|     } else if (y + 1 == yn) { |  | ||||||
|       printf("\e[0m⎯yn"); |  | ||||||
|     } else if (y + 2 == yn) { |  | ||||||
|       printf("\e[0m_yn"); |  | ||||||
|     } else if (!(y % 10)) { |  | ||||||
|       printf("\e[0m‾%,u", y); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   printf("\e[0m\n"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static dontinline void *DeblinterlaceRgba2(unsigned yn, unsigned xn, |  | ||||||
|                                            unsigned char D[4][yn][xn], |  | ||||||
|                                            const unsigned char S[yn][xn][4]) { |  | ||||||
|   unsigned y, x; |  | ||||||
|   for (y = 0; y < yn; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       D[0][y][x] = S[y][x][0]; |  | ||||||
|       D[1][y][x] = S[y][x][1]; |  | ||||||
|       D[2][y][x] = S[y][x][2]; |  | ||||||
|       D[3][y][x] = S[y][x][3]; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   return D; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ProcessImageBilinearImpl(unsigned dyn, unsigned dxn, |  | ||||||
|                               unsigned char dst[4][dyn][dxn], unsigned syn, |  | ||||||
|                               unsigned sxn, unsigned char src[4][syn][sxn], |  | ||||||
|                               unsigned char img[syn][sxn][4]) { |  | ||||||
|   DeblinterlaceRgba2(syn, sxn, src, img); |  | ||||||
|   BilinearScale(4, dyn, dxn, dst, 4, syn, sxn, src, 0, 4, dyn, dxn, syn, sxn, |  | ||||||
|                 r_, r_, 0, 0); |  | ||||||
|   PrintImage2(dyn, dxn, dst, dyn, dxn); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ProcessImageBilinear(unsigned yn, unsigned xn, |  | ||||||
|                           unsigned char img[yn][xn][4]) { |  | ||||||
|   unsigned dyn, dxn; |  | ||||||
|   dyn = lround(yn / r_); |  | ||||||
|   dxn = lround(xn / r_); |  | ||||||
|   ProcessImageBilinearImpl(dyn, dxn, gc(xmalloc(dyn * dxn * 4)), yn, xn, |  | ||||||
|                            gc(xmalloc(yn * xn * 4)), img); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void *b2f(long n, float dst[n], const unsigned char src[n]) { |  | ||||||
|   long i; |  | ||||||
|   float f; |  | ||||||
|   for (i = 0; i < n; ++i) { |  | ||||||
|     f = src[i]; |  | ||||||
|     f *= 1 / 255.; |  | ||||||
|     dst[i] = f; |  | ||||||
|   } |  | ||||||
|   return dst; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void *f2b(long n, unsigned char dst[n], const float src[n]) { |  | ||||||
|   int x; |  | ||||||
|   long i; |  | ||||||
|   for (i = 0; i < n; ++i) { |  | ||||||
|     x = lroundf(src[i] * 255); |  | ||||||
|     dst[i] = MIN(255, MAX(0, x)); |  | ||||||
|   } |  | ||||||
|   return dst; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ProcessImageGyarados(unsigned yn, unsigned xn, |  | ||||||
|                           unsigned char img[yn][xn][4]) { |  | ||||||
|   unsigned dyn, dxn; |  | ||||||
|   dyn = lround(yn / r_); |  | ||||||
|   dxn = lround(xn / r_); |  | ||||||
|   PrintImage2( |  | ||||||
|       dyn, dxn, |  | ||||||
|       EzGyarados(4, dyn, dxn, gc(xmalloc(dyn * dxn * 4)), 4, yn, xn, |  | ||||||
|                  DeblinterlaceRgba2(yn, xn, gc(xmalloc(yn * xn * 4)), img), 0, |  | ||||||
|                  4, dyn, dxn, yn, xn, r_, r_, 0, 0), |  | ||||||
|       dyn, dxn); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void MagikarpDecimate(int yw, int xw, unsigned char img[4][yw][xw], int yn, |  | ||||||
|                       int xn, int n) { |  | ||||||
|   int c; |  | ||||||
|   if (n <= 1) { |  | ||||||
|     PrintImage2(yw, xw, img, yn, xn); |  | ||||||
|   } else { |  | ||||||
|     for (c = 0; c < 4; ++c) Magikarp2xY(yw, xw, img[c], yn, xn); |  | ||||||
|     for (c = 0; c < 4; ++c) Magikarp2xX(yw, xw, img[c], (yn + 1) / 2, xn); |  | ||||||
|     MagikarpDecimate(yw, xw, img, (yn + 1) / 2, (xn + 1) / 2, (n + 1) / 2); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ProcessImageMagikarp(unsigned yn, unsigned xn, |  | ||||||
|                           unsigned char img[yn][xn][4]) { |  | ||||||
|   MagikarpDecimate(yn, xn, |  | ||||||
|                    DeblinterlaceRgba2(yn, xn, gc(xmalloc(yn * xn * 4)), img), |  | ||||||
|                    yn, xn, lround(r_)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| dontinline void WithImageFile(const char *path, |  | ||||||
|                               void fn(unsigned yn, unsigned xn, |  | ||||||
|                                       unsigned char img[yn][xn][4])) { |  | ||||||
|   struct stat st; |  | ||||||
|   int fd, yn, xn; |  | ||||||
|   void *map, *data; |  | ||||||
|   CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path); |  | ||||||
|   CHECK_NE(-1, fstat(fd, &st)); |  | ||||||
|   CHECK_GT(st.st_size, 0); |  | ||||||
|   CHECK_LE(st.st_size, INT_MAX); |  | ||||||
|   fadvise(fd, 0, 0, MADV_WILLNEED | MADV_SEQUENTIAL); |  | ||||||
|   CHECK_NE(MAP_FAILED, |  | ||||||
|            (map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0))); |  | ||||||
|   CHECK_NOTNULL( |  | ||||||
|       (data = stbi_load_from_memory(map, st.st_size, &xn, &yn, NULL, 4)), "%s", |  | ||||||
|       path); |  | ||||||
|   CHECK_NE(-1, munmap(map, st.st_size)); |  | ||||||
|   CHECK_NE(-1, close(fd)); |  | ||||||
|   fn(yn, xn, data); |  | ||||||
|   free(data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int i, opt; |  | ||||||
|   bool bilinear; |  | ||||||
|   void (*scaler)(unsigned yn, unsigned xn, unsigned char[yn][xn][4]) = |  | ||||||
|       ProcessImageMagikarp; |  | ||||||
|   r_ = 2; |  | ||||||
|   while ((opt = getopt(argc, argv, "mlsSybr:")) != -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case 'r': |  | ||||||
|         r_ = strtod(optarg, NULL); |  | ||||||
|         break; |  | ||||||
|       case 'm': |  | ||||||
|         scaler = ProcessImageMagikarp; |  | ||||||
|         break; |  | ||||||
|       case 's': |  | ||||||
|       case 'S': |  | ||||||
|         scaler = ProcessImageGyarados; |  | ||||||
|         break; |  | ||||||
|       case 'b': |  | ||||||
|         scaler = ProcessImageBilinear; |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   ShowCrashReports(); |  | ||||||
|   for (i = optind; i < argc; ++i) { |  | ||||||
|     WithImageFile(argv[i], scaler); |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,95 +0,0 @@ | ||||||
| #if 0 |  | ||||||
| /*─────────────────────────────────────────────────────────────────╗
 |  | ||||||
| │ To the extent possible under law, Justine Tunney has waived      │ |  | ||||||
| │ all copyright and related or neighboring rights to this file,    │ |  | ||||||
| │ as it is written in the following disclaimers:                   │ |  | ||||||
| │   • http://unlicense.org/                                        │
 |  | ||||||
| │   • http://creativecommons.org/publicdomain/zero/1.0/            │
 |  | ||||||
| ╚─────────────────────────────────────────────────────────────────*/ |  | ||||||
| #endif |  | ||||||
| #include "libc/calls/internal.h" |  | ||||||
| #include "libc/fmt/conv.h" |  | ||||||
| #include "libc/fmt/itoa.h" |  | ||||||
| #include "libc/intrin/bits.h" |  | ||||||
| #include "libc/macros.internal.h" |  | ||||||
| #include "libc/runtime/memtrack.internal.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| // clang-format off
 |  | ||||||
| 
 |  | ||||||
| struct WinArgs { |  | ||||||
|   char *argv[4096]; |  | ||||||
|   char *envp[4092]; |  | ||||||
|   intptr_t auxv[2][2]; |  | ||||||
|   char argblock[ARG_MAX / 2]; |  | ||||||
|   char envblock[ARG_MAX / 2]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| //#define INCREMENT _roundup2pow(kAutomapSize/16)
 |  | ||||||
| #define INCREMENT (64L*1024*1024*1024) |  | ||||||
| 
 |  | ||||||
| uint64_t last; |  | ||||||
| 
 |  | ||||||
| void plan2(uint64_t addr, uint64_t end, const char *name) { |  | ||||||
|   char sz[32]; |  | ||||||
|   sizefmt(sz, end-addr+1, 1024); |  | ||||||
|   printf("%08x-%08x %-6s %s\n", addr>>16, end>>16, sz, name); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void plan(uint64_t addr, uint64_t end, const char *name) { |  | ||||||
|   uint64_t incr, next; |  | ||||||
|   while (addr > last) { |  | ||||||
|     if ((incr = last % INCREMENT)) { |  | ||||||
|       incr = INCREMENT - incr; |  | ||||||
|     } else { |  | ||||||
|       incr = INCREMENT; |  | ||||||
|     } |  | ||||||
|     plan2(last,MIN(last+incr,addr)-1,"free"); |  | ||||||
|     last = MIN(last+incr,addr); |  | ||||||
|   } |  | ||||||
|   while (addr <= end) { |  | ||||||
|     if (end-addr+1 <= INCREMENT) { |  | ||||||
|       plan2(addr,end,name); |  | ||||||
|       last = end + 1; |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|     if (!(addr % INCREMENT)) { |  | ||||||
|       plan2(addr, addr + INCREMENT - 1, name); |  | ||||||
|       last = addr + INCREMENT; |  | ||||||
|       addr += INCREMENT; |  | ||||||
|     } else { |  | ||||||
|       next = INCREMENT - addr % INCREMENT + addr; |  | ||||||
|       plan2(addr, next - 1, name); |  | ||||||
|       last = next; |  | ||||||
|       addr = next; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   uint64_t x, y; |  | ||||||
| 
 |  | ||||||
|   plan(0x00000000, 0x00200000-1, "null"); |  | ||||||
|   plan(0x00200000, 0x00400000-1, "loader"); |  | ||||||
|   if (!IsWindows() || IsAtLeastWindows10()) { |  | ||||||
|     plan(0x00400000, 0x50000000-1, "image"); |  | ||||||
|     plan(0x50000000, 0x7ffdffff, "arena"); |  | ||||||
|     plan(0x7fff0000, 0x10007fffffff, "asan"); |  | ||||||
|   } else { |  | ||||||
|     plan(0x00400000, 0x01000000-1, "image"); |  | ||||||
|   } |  | ||||||
|   plan(kAutomapStart, kAutomapStart + kAutomapSize - 1, "automap"); |  | ||||||
|   plan(kMemtrackStart, kMemtrackStart + kMemtrackSize - 1, "memtrack"); |  | ||||||
|   plan(kFixedmapStart, kFixedmapStart + kFixedmapSize - 1, "fixedmap"); |  | ||||||
|   if (IsWindows() && !IsAtLeastWindows10()) { |  | ||||||
|     plan(0x50000000, 0x7ffdffff, "arena"); |  | ||||||
|   } |  | ||||||
|   x = GetStaticStackAddr(0); |  | ||||||
|   y = ROUNDUP(sizeof(struct WinArgs), FRAMESIZE); |  | ||||||
|   plan(x - y, x - 1, "winargs"); |  | ||||||
|   plan(x, x + GetStackSize() - 1, "stack"); |  | ||||||
|   if (!IsWindows() || IsAtLeastWindows10()) { |  | ||||||
|     plan(0x7f0000000000, 0x800000000000 - 1, "kernel"); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,83 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2021 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 "libc/macros.internal.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/x/xgetline.h" |  | ||||||
| 
 |  | ||||||
| #define DLL "iphlpapi" |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * @fileoverview Tool for adding rnew libraries to libc/nt/master.sh |  | ||||||
|  * |  | ||||||
|  * If provided with a /tmp/syms.txt file containing one symbol name per |  | ||||||
|  * line, this tool will output the correctly tab indented shell code. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   FILE *f; |  | ||||||
|   int i, n, t; |  | ||||||
|   char *sym, tabs[64]; |  | ||||||
|   ShowCrashReports(); |  | ||||||
|   f = fopen("/tmp/syms.txt", "r"); |  | ||||||
|   memset(tabs, '\t', 64); |  | ||||||
|   while ((sym = _chomp(xgetline(f)))) { |  | ||||||
|     if (strlen(sym)) { |  | ||||||
|       printf("imp\t"); |  | ||||||
| 
 |  | ||||||
|       /* what we call the symbol */ |  | ||||||
|       i = printf("'%s'", sym); |  | ||||||
|       t = 0; |  | ||||||
|       n = 56; |  | ||||||
|       if (i % 8) ++t, i = ROUNDUP(i, 8); |  | ||||||
|       t += (n - i) / 8; |  | ||||||
|       printf("%.*s", t, tabs); |  | ||||||
| 
 |  | ||||||
|       /* what the kernel dll calls the symbol */ |  | ||||||
|       i = printf("%s", sym); |  | ||||||
|       t = 0; |  | ||||||
|       n = 56; |  | ||||||
|       if (i % 8) ++t, i = ROUNDUP(i, 8); |  | ||||||
|       t += (n - i) / 8; |  | ||||||
|       printf("%.*s", t, tabs); |  | ||||||
| 
 |  | ||||||
|       /* dll short name */ |  | ||||||
|       i = printf("%s", DLL); |  | ||||||
|       t = 0; |  | ||||||
|       n = 16; |  | ||||||
|       if (i % 8) ++t, i = ROUNDUP(i, 8); |  | ||||||
|       t += (n - i) / 8; |  | ||||||
|       printf("%.*s", t, tabs); |  | ||||||
| 
 |  | ||||||
|       /* hint */ |  | ||||||
|       i = printf("0"); |  | ||||||
|       t = 0; |  | ||||||
|       n = 8; |  | ||||||
|       if (i % 8) ++t, i = ROUNDUP(i, 8); |  | ||||||
|       t += (n - i) / 8; |  | ||||||
|       printf("%.*s", t, tabs); |  | ||||||
| 
 |  | ||||||
|       printf("\n"); |  | ||||||
|     } |  | ||||||
|     free(sym); |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,45 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "dsp/tty/quant.h" |  | ||||||
| #include "dsp/tty/xtermname.h" |  | ||||||
| #include "libc/fmt/conv.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int i; |  | ||||||
|   struct TtyRgb tty; |  | ||||||
|   unsigned rgb, r, g, b; |  | ||||||
|   if (argc < 2) { |  | ||||||
|     fprintf(stderr, "Usage: %s RRGGBB...\n", program_invocation_name); |  | ||||||
|     exit(EX_USAGE); |  | ||||||
|   } |  | ||||||
|   for (i = 1; i < argc; ++i) { |  | ||||||
|     rgb = strtol(argv[i], NULL, 16); |  | ||||||
|     b = (rgb & 0x0000ff) >> 000; |  | ||||||
|     g = (rgb & 0x00ff00) >> 010; |  | ||||||
|     r = (rgb & 0xff0000) >> 020; |  | ||||||
|     tty = rgb2tty(r, g, b); |  | ||||||
|     printf("\e[48;5;%dm    \e[0m %d \\e[48;5;%dm %s #%02x%02x%02x\n", tty.xt, |  | ||||||
|            tty.xt, tty.xt, IndexDoubleNulString(kXtermName, tty.xt), r, g, b); |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,135 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "dsp/tty/quant.h" |  | ||||||
| #include "libc/calls/calls.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/exit.h" |  | ||||||
| #include "libc/sysv/consts/fileno.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| 
 |  | ||||||
| #define kUsage \ |  | ||||||
|   "Usage:\n\
 |  | ||||||
| \n\ |  | ||||||
|   %s [-cber] [-o FILE] [ARGS...]\n\ |  | ||||||
| \n\ |  | ||||||
| Flags:\n\ |  | ||||||
| \n\ |  | ||||||
|   -e         enable emphasis\n\ |  | ||||||
|   -b         emit as background color\n\ |  | ||||||
|   -r         print raw codes\n\ |  | ||||||
|   -c         emit cleanup (reset) codes when done\n\ |  | ||||||
|   -o FILE    redirects output [default: /dev/stdout]\n\ |  | ||||||
| \n\ |  | ||||||
| Arguments:\n\ |  | ||||||
| \n\ |  | ||||||
|   - may be passed via ARGS or STDIN (one per line)\n\ |  | ||||||
|   - may be #RRGGBB or RRGGBB\n\ |  | ||||||
|   - may be #RGB or RGB (#123 → #112233)\n\ |  | ||||||
|   - anything else is printed verbatim\n\ |  | ||||||
| \n" |  | ||||||
| 
 |  | ||||||
| static FILE *fout_; |  | ||||||
| static size_t linecap_; |  | ||||||
| static char *outpath_, *line_; |  | ||||||
| static bool rawmode_, background_, emphasis_, cleanup_; |  | ||||||
| 
 |  | ||||||
| wontreturn void usage(int rc, FILE *f) { |  | ||||||
|   fprintf(f, kUsage, program_invocation_name); |  | ||||||
|   exit(rc); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void getopts(int *argc, char *argv[]) { |  | ||||||
|   int opt; |  | ||||||
|   outpath_ = "-"; |  | ||||||
|   while ((opt = getopt(*argc, argv, "?hrecbo:")) != -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case 'r': |  | ||||||
|         rawmode_ = true; |  | ||||||
|         break; |  | ||||||
|       case 'b': |  | ||||||
|         background_ = true; |  | ||||||
|         break; |  | ||||||
|       case 'c': |  | ||||||
|         cleanup_ = true; |  | ||||||
|         break; |  | ||||||
|       case 'e': |  | ||||||
|         emphasis_ = true; |  | ||||||
|         break; |  | ||||||
|       case 'o': |  | ||||||
|         outpath_ = optarg; |  | ||||||
|         break; |  | ||||||
|       case '?': |  | ||||||
|       case 'h': |  | ||||||
|         usage(EXIT_SUCCESS, stdout); |  | ||||||
|       default: |  | ||||||
|         usage(EX_USAGE, stderr); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void processarg(const char *arg) { |  | ||||||
|   const char *p; |  | ||||||
|   size_t r, g, b; |  | ||||||
|   if (*(p = arg) == '#') p++; |  | ||||||
|   if (strlen(p) == 3 && (isxdigit(p[0]) && isxdigit(p[1]) && isxdigit(p[2]))) { |  | ||||||
|     r = hextoint(p[0]) << 4 | hextoint(p[0]); |  | ||||||
|     g = hextoint(p[1]) << 4 | hextoint(p[1]); |  | ||||||
|     b = hextoint(p[2]) << 4 | hextoint(p[2]); |  | ||||||
|   } else if (strlen(p) == 6 && |  | ||||||
|              (isxdigit(p[0]) && isxdigit(p[1]) && isxdigit(p[2]) && |  | ||||||
|               isxdigit(p[3]) && isxdigit(p[4]) && isxdigit(p[5]))) { |  | ||||||
|     r = hextoint(p[0]) << 4 | hextoint(p[1]); |  | ||||||
|     g = hextoint(p[2]) << 4 | hextoint(p[3]); |  | ||||||
|     b = hextoint(p[4]) << 4 | hextoint(p[5]); |  | ||||||
|   } else { |  | ||||||
|     fputs(arg, fout_); |  | ||||||
|     return; |  | ||||||
|   } |  | ||||||
|   fprintf(fout_, "%s[%s%d;5;%hhum%s", rawmode_ ? "\e" : "\\e", |  | ||||||
|           emphasis_ ? "1;" : "", background_ ? 48 : 38, rgb2tty(r, g, b).xt, |  | ||||||
|           &"\n"[rawmode_]); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   size_t i; |  | ||||||
|   getopts(&argc, argv); |  | ||||||
|   CHECK_NOTNULL((fout_ = fopen(outpath_, "w"))); |  | ||||||
|   if (optind < argc) { |  | ||||||
|     for (i = optind; i < argc; ++i) { |  | ||||||
|       processarg(argv[i]); |  | ||||||
|     } |  | ||||||
|   } else { |  | ||||||
|     while ((getline(&line_, &linecap_, stdin)) != -1) { |  | ||||||
|       processarg(_chomp(line_)); |  | ||||||
|     } |  | ||||||
|     free(line_); |  | ||||||
|     line_ = 0; |  | ||||||
|   } |  | ||||||
|   if (cleanup_) { |  | ||||||
|     fprintf(fout_, "%s[0m\n", rawmode_ ? "\e" : "\\e"); |  | ||||||
|   } |  | ||||||
|   CHECK_NE(-1, fclose(fout_)); |  | ||||||
|   fout_ = 0; |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,177 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/fmt/conv.h" |  | ||||||
| #include "libc/intrin/safemacros.internal.h" |  | ||||||
| #include "libc/limits.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/log/log.h" |  | ||||||
| #include "libc/mem/arraylist.internal.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/str/strwidth.h" |  | ||||||
| #include "libc/str/unicode.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/exit.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| 
 |  | ||||||
| #define kOneTrueTabWidth 8 |  | ||||||
| 
 |  | ||||||
| struct Pool { |  | ||||||
|   size_t i, n; |  | ||||||
|   char *p; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct Lines { |  | ||||||
|   size_t i, n; |  | ||||||
|   struct Line { |  | ||||||
|     uint16_t off; |  | ||||||
|     uint16_t col; |  | ||||||
|     int32_t line; |  | ||||||
|   } * p; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static bool chunk_; |  | ||||||
| static FILE *fi_, *fo_; |  | ||||||
| static struct Pool pool_; |  | ||||||
| static struct Lines lines_; |  | ||||||
| static size_t mincol_, col_, maxcol_, linecap_; |  | ||||||
| static char *inpath_, *outpath_, *delim_, *line_; |  | ||||||
| 
 |  | ||||||
| wontreturn void usage(int rc, FILE *f) { |  | ||||||
|   fprintf(f, "%s%s%s\n", "Usage: ", program_invocation_name, |  | ||||||
|           " [-c] [-m MINCOL] [-M MAXCOL] [-F DELIM] [-o FILE] [FILE...]\n" |  | ||||||
|           "\n" |  | ||||||
|           "  This program aligns monospace text. It's aware of tabs,\n" |  | ||||||
|           "  color codes, wide characters, combining characters etc.\n"); |  | ||||||
|   exit(rc); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void getopts(int *argc, char *argv[]) { |  | ||||||
|   int opt; |  | ||||||
|   delim_ = "#"; |  | ||||||
|   outpath_ = "-"; |  | ||||||
|   while ((opt = getopt(*argc, argv, "?hco:m:M:F:")) != -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case 'm': |  | ||||||
|         mincol_ = strtol(optarg, NULL, 0); |  | ||||||
|         break; |  | ||||||
|       case 'M': |  | ||||||
|         maxcol_ = strtol(optarg, NULL, 0); |  | ||||||
|         break; |  | ||||||
|       case 'c': |  | ||||||
|         chunk_ = true; |  | ||||||
|         break; |  | ||||||
|       case 'o': |  | ||||||
|         outpath_ = optarg; |  | ||||||
|         break; |  | ||||||
|       case 'F': |  | ||||||
|         delim_ = optarg; |  | ||||||
|         break; |  | ||||||
|       case '?': |  | ||||||
|       case 'h': |  | ||||||
|         usage(EXIT_SUCCESS, stdout); |  | ||||||
|       default: |  | ||||||
|         usage(EX_USAGE, stderr); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (optind == *argc) { |  | ||||||
|     argv[(*argc)++] = "-"; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void flush(void) { |  | ||||||
|   size_t i, j; |  | ||||||
|   const char *s; |  | ||||||
|   struct Line l; |  | ||||||
|   col_ = roundup(col_ + 1, kOneTrueTabWidth); |  | ||||||
|   if (maxcol_) col_ = min(col_, maxcol_); |  | ||||||
|   for (i = 0; i < lines_.i; ++i) { |  | ||||||
|     l = lines_.p[i]; |  | ||||||
|     s = &pool_.p[l.line]; |  | ||||||
|     if (l.off < USHRT_MAX) { |  | ||||||
|       fwrite(s, l.off, 1, fo_); |  | ||||||
|       for (j = l.col; j < col_;) { |  | ||||||
|         fputc('\t', fo_); |  | ||||||
|         if (j % kOneTrueTabWidth == 0) { |  | ||||||
|           j += 8; |  | ||||||
|         } else { |  | ||||||
|           j += kOneTrueTabWidth - (j & (kOneTrueTabWidth - 1)); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       fwrite(s + l.off, strlen(s) - l.off, 1, fo_); |  | ||||||
|     } else { |  | ||||||
|       fwrite(s, strlen(s), 1, fo_); |  | ||||||
|     } |  | ||||||
|     fputc('\n', fo_); |  | ||||||
|   } |  | ||||||
|   col_ = mincol_; |  | ||||||
|   pool_.i = 0; |  | ||||||
|   lines_.i = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void processfile(void) { |  | ||||||
|   char *p; |  | ||||||
|   int col, s; |  | ||||||
|   size_t off, len; |  | ||||||
|   while ((getline(&line_, &linecap_, fi_)) != -1) { |  | ||||||
|     _chomp(line_); |  | ||||||
|     len = strlen(line_); |  | ||||||
|     s = concat(&pool_, line_, len + 1); |  | ||||||
|     if (len < USHRT_MAX) { |  | ||||||
|       if ((p = strstr(line_, delim_))) { |  | ||||||
|         off = p - line_; |  | ||||||
|         col = strnwidth(line_, off, 0); |  | ||||||
|         if (col < USHRT_MAX) { |  | ||||||
|           col_ = max(col_, col); |  | ||||||
|           append(&lines_, &((struct Line){.line = s, .off = off, .col = col})); |  | ||||||
|           continue; |  | ||||||
|         } |  | ||||||
|       } else { |  | ||||||
|         if (chunk_) { |  | ||||||
|           flush(); |  | ||||||
|           fputs(line_, fo_); |  | ||||||
|           fputc('\n', fo_); |  | ||||||
|           continue; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     append(&lines_, &((struct Line){.line = s, .off = 0xffff, .col = 0xffff})); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   size_t i; |  | ||||||
|   getopts(&argc, argv); |  | ||||||
|   CHECK_NOTNULL((fo_ = fopen(outpath_, "w"))); |  | ||||||
|   for (i = optind; i < argc; ++i) { |  | ||||||
|     CHECK_NOTNULL((fi_ = fopen((inpath_ = argv[i]), "r"))); |  | ||||||
|     processfile(); |  | ||||||
|     CHECK_NE(-1, fclose(fi_)); |  | ||||||
|     fi_ = 0; |  | ||||||
|   } |  | ||||||
|   flush(); |  | ||||||
|   CHECK_NE(-1, fclose(fo_)); |  | ||||||
|   fo_ = 0; |  | ||||||
|   free(lines_.p); |  | ||||||
|   free(pool_.p); |  | ||||||
|   free(line_); |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
							
								
								
									
										156
									
								
								tool/viz/tcp.c
									
										
									
									
									
								
							
							
						
						
									
										156
									
								
								tool/viz/tcp.c
									
										
									
									
									
								
							|  | @ -1,156 +0,0 @@ | ||||||
| #if 0 |  | ||||||
| /*─────────────────────────────────────────────────────────────────╗
 |  | ||||||
| │ To the extent possible under law, Justine Tunney has waived      │ |  | ||||||
| │ all copyright and related or neighboring rights to this file,    │ |  | ||||||
| │ as it is written in the following disclaimers:                   │ |  | ||||||
| │   • http://unlicense.org/                                        │
 |  | ||||||
| │   • http://creativecommons.org/publicdomain/zero/1.0/            │
 |  | ||||||
| ╚─────────────────────────────────────────────────────────────────*/ |  | ||||||
| #endif |  | ||||||
| #include "libc/intrin/bits.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| // clang-format off
 |  | ||||||
| 
 |  | ||||||
| static char ip[] = "\
 |  | ||||||
| \x45\x00\x00\x3c\xc8\xbc\x40\x00\x40\x06\x48\xf6\x7f\x0a\x0a\x7a\ |  | ||||||
| \x7f\x0a\x0a\x7c\xe2\x24\x1b\x58\xf6\xe9\xf2\x85\x00\x00\x00\x00\ |  | ||||||
| \xa0\x02\xfa\xf0\x5f\xac\x00\x00\x02\x04\x05\xb4\x04\x02\x08\x0a\ |  | ||||||
| \x4a\x43\x93\x29\x00\x00\x00\x00\x01\x03\x03\x07"; |  | ||||||
| 
 |  | ||||||
| static const char *const kTcpOptionNames[] = { |  | ||||||
|     [0] = "End of Option List", |  | ||||||
|     [1] = "No-Operation", |  | ||||||
|     [2] = "Maximum Segment Size", |  | ||||||
|     [3] = "Window Scale", |  | ||||||
|     [4] = "SACK Permitted", |  | ||||||
|     [5] = "SACK", |  | ||||||
|     [6] = "Echo (obsoleted by option 8)", |  | ||||||
|     [7] = "Echo Reply (obsoleted by option 8)", |  | ||||||
|     [8] = "Timestamps", |  | ||||||
|     [9] = "Partial Order Connection Permitted (obsolete)", |  | ||||||
|     [10] = "Partial Order Service Profile (obsolete)", |  | ||||||
|     [11] = "CC (obsolete)", |  | ||||||
|     [12] = "CC.NEW (obsolete)", |  | ||||||
|     [13] = "CC.ECHO (obsolete)", |  | ||||||
|     [14] = "TCP Alternate Checksum Request (obsolete)", |  | ||||||
|     [15] = "TCP Alternate Checksum Data (obsolete)", |  | ||||||
|     [16] = "Skeeter", |  | ||||||
|     [17] = "Bubba", |  | ||||||
|     [18] = "Trailer Checksum Option", |  | ||||||
|     [19] = "MD5 Signature Option (obsoleted by option 29)", |  | ||||||
|     [20] = "SCPS Capabilities", |  | ||||||
|     [21] = "Selective Negative Acknowledgements", |  | ||||||
|     [22] = "Record Boundaries", |  | ||||||
|     [23] = "Corruption experienced", |  | ||||||
|     [24] = "SNAP", |  | ||||||
|     [25] = "Unassigned (released 2000-12-18)", |  | ||||||
|     [26] = "TCP Compression Filter", |  | ||||||
|     [27] = "Quick-Start Response", |  | ||||||
|     [28] = "User Timeout Option", |  | ||||||
|     [29] = "TCP Authentication Option (TCP-AO)", |  | ||||||
|     [30] = "Multipath TCP (MPTCP)", |  | ||||||
|     [31] = "Reserved (known unauthorized use without proper IANA assignm", |  | ||||||
|     [32] = "Reserved (known unauthorized use without proper IANA assignm", |  | ||||||
|     [33] = "Reserved (known unauthorized use without proper IANA assignm", |  | ||||||
|     [34] = "variable TCP Fast Open Cookie", |  | ||||||
|     [35] = "Reserved", |  | ||||||
|     [69] = "Encryption Negotiation", |  | ||||||
|     [253] = "RFC3692-1", |  | ||||||
|     [254] = "RFC3692-2", |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int version = (ip[0] & 0b11110000) >> 4; |  | ||||||
|   int ihl = (ip[0] & 0b00001111) >> 0; |  | ||||||
|   int dscp = (ip[1] & 0b11111100) >> 2; |  | ||||||
|   int ecn = (ip[1] & 0b00000011) >> 0; |  | ||||||
|   int lengthtotal = READ16BE(ip + 2); |  | ||||||
|   int identification = READ16BE(ip + 4); |  | ||||||
|   int flags = (ip[6] & 0b11100000) >> 5; |  | ||||||
|   int fragmentoffset = (ip[6] & 0b00011111) << 8 | (ip[7] & 255); |  | ||||||
|   int ttl = ip[8] & 255; |  | ||||||
|   int protocol = ip[9] & 255; |  | ||||||
|   int ipchecksum = (ip[10] & 255) << 8 | (ip[11] & 255); |  | ||||||
|   int srcip = READ32BE(ip + 12); |  | ||||||
|   int dstip = READ32BE(ip + 16); |  | ||||||
| 
 |  | ||||||
|   printf("\n"); |  | ||||||
|   printf("// version        = %u\n", version); |  | ||||||
|   printf("// ihl            = %u\n", ihl * 4); |  | ||||||
|   printf("// dscp           = %u\n", dscp); |  | ||||||
|   printf("// ecn            = %u\n", ecn); |  | ||||||
|   printf("// lengthtotal    = %u\n", lengthtotal); |  | ||||||
|   printf("// identification = %u\n", identification); |  | ||||||
|   printf("// flags          = %u\n", flags); |  | ||||||
|   printf("// fragmentoffset = %u\n", fragmentoffset); |  | ||||||
|   printf("// ttl            = %u\n", ttl); |  | ||||||
|   printf("// protocol       = %u\n", protocol); |  | ||||||
|   printf("// ipchecksum     = %u\n", ipchecksum); |  | ||||||
|   printf("// srcip          = %hhu.%hhu.%hhu.%hhu\n", srcip >> 24, srcip >> 16, srcip >> 8, srcip); |  | ||||||
|   printf("// dstip          = %hhu.%hhu.%hhu.%hhu\n", dstip >> 24, dstip >> 16, dstip >> 8, dstip); |  | ||||||
|   printf("// \n"); |  | ||||||
| 
 |  | ||||||
|   char *tcp = ip + ihl * 4; |  | ||||||
|   int srcport = READ16BE(tcp + 0); |  | ||||||
|   int dstport = READ16BE(tcp + 2); |  | ||||||
|   int sequence = READ32BE(tcp + 4); |  | ||||||
|   int acknumber = READ32BE(tcp + 8); |  | ||||||
|   int dataoffset = (tcp[12] & 0b11110000) >> 4; |  | ||||||
|   bool ns = !!(tcp[12] & 0b00000001); |  | ||||||
|   bool cwr = !!(tcp[13] & 0b10000000); |  | ||||||
|   bool ece = !!(tcp[13] & 0b01000000); |  | ||||||
|   bool urg = !!(tcp[13] & 0b00100000); |  | ||||||
|   bool ack = !!(tcp[13] & 0b00010000); |  | ||||||
|   bool psh = !!(tcp[13] & 0b00001000); |  | ||||||
|   bool rst = !!(tcp[13] & 0b00000100); |  | ||||||
|   bool syn = !!(tcp[13] & 0b00000010); |  | ||||||
|   bool fin = !!(tcp[13] & 0b00000001); |  | ||||||
|   int wsize = READ16BE(tcp + 14); |  | ||||||
|   int tcpchecksum = READ16BE(tcp + 16); |  | ||||||
|   int urgpointer = READ16BE(tcp + 18); |  | ||||||
| 
 |  | ||||||
|   printf("// srcport     = %u\n", srcport); |  | ||||||
|   printf("// dstport     = %u\n", dstport); |  | ||||||
|   printf("// sequence    = %u\n", sequence); |  | ||||||
|   printf("// acknumber   = %u\n", acknumber); |  | ||||||
|   printf("// dataoffset  = %u\n", dataoffset); |  | ||||||
|   printf("// ns          = %u\n", ns); |  | ||||||
|   printf("// cwr         = %u\n", cwr); |  | ||||||
|   printf("// ece         = %u\n", ece); |  | ||||||
|   printf("// urg         = %u\n", urg); |  | ||||||
|   printf("// ack         = %u\n", ack); |  | ||||||
|   printf("// psh         = %u\n", psh); |  | ||||||
|   printf("// rst         = %u\n", rst); |  | ||||||
|   printf("// syn         = %u\n", syn); |  | ||||||
|   printf("// fin         = %u\n", fin); |  | ||||||
|   printf("// wsize       = %u\n", wsize); |  | ||||||
|   printf("// tcpchecksum = %u\n", tcpchecksum); |  | ||||||
|   printf("// urgpointer  = %u\n", urgpointer); |  | ||||||
|   printf("// \n"); |  | ||||||
| 
 |  | ||||||
|   int c, i, j, n; |  | ||||||
|   for (i = 20; i + 1 < dataoffset * 4;) { |  | ||||||
|     printf("// option"); |  | ||||||
|     switch ((c = tcp[i] & 255)) { |  | ||||||
|       case 0: |  | ||||||
|       case 1: |  | ||||||
|         printf(" %u", c); |  | ||||||
|         ++i; |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         n = tcp[i + 1] & 255; |  | ||||||
|         printf(" %u %u", c, n); |  | ||||||
|         for (j = 2; j < n; ++j) { |  | ||||||
|           printf(" %u", tcp[i + j] & 255); |  | ||||||
|         } |  | ||||||
|         i += n; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|     if (kTcpOptionNames[c]) { |  | ||||||
|       printf(" (%s)", kTcpOptionNames[c]); |  | ||||||
|     } |  | ||||||
|     printf("\n"); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,91 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/str/unicode.h" |  | ||||||
| #include "libc/fmt/fmt.h" |  | ||||||
| #include "libc/mem/gc.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/x/xasprintf.h" |  | ||||||
| 
 |  | ||||||
| int a, b, w, i; |  | ||||||
| char name[512]; |  | ||||||
| 
 |  | ||||||
| void DisplayUnicodeCharacter(void) { |  | ||||||
|   int c, cw; |  | ||||||
|   c = i; |  | ||||||
|   cw = wcwidth(c); |  | ||||||
|   if (cw < 1) { |  | ||||||
|     c = '?'; |  | ||||||
|     cw = 1; |  | ||||||
|   } |  | ||||||
|   if (w) { |  | ||||||
|     if (w + 1 + cw > 80) { |  | ||||||
|       printf("\n"); |  | ||||||
|       w = 0; |  | ||||||
|     } else { |  | ||||||
|       fputc(' ', stdout); |  | ||||||
|       w += 1 + cw; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (!w) { |  | ||||||
|     printf("%08x ", i); |  | ||||||
|     w = 9 + cw; |  | ||||||
|   } |  | ||||||
|   fputwc(c, stdout); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void DisplayUnicodeBlock(void) { |  | ||||||
|   if (a == 0x10000) { |  | ||||||
|     printf("\n\n\n\n\n\n\n                                " |  | ||||||
|            "ASTRAL PLANES\n\n\n\n\n"); |  | ||||||
|   } |  | ||||||
|   if (a == 0x0590 /* hebrew */) return; |  | ||||||
|   if (a == 0x0600 /* arabic */) return; |  | ||||||
|   if (a == 0x08a0 /* arabic */) return; |  | ||||||
|   if (a == 0x0750 /* arabic */) return; |  | ||||||
|   if (a == 0x0700 /* syriac */) return; |  | ||||||
|   if (a == 0x10800 /* cypriot */) return; |  | ||||||
|   printf("\n\n%-60s%20s\n" |  | ||||||
|          "──────────────────────────────────────────────" |  | ||||||
|          "──────────────────────────────────\n", |  | ||||||
|          name, _gc(xasprintf("%04x .. %04x", a, b))); |  | ||||||
|   w = 0; |  | ||||||
|   for (i = a; i <= b; ++i) { |  | ||||||
|     DisplayUnicodeCharacter(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   FILE *f; |  | ||||||
|   char *line; |  | ||||||
|   size_t linesize; |  | ||||||
|   printf("\n\n\n\n\n                                UNICODE PLANES\n\n\n\n"); |  | ||||||
|   f = fopen("libc/str/blocks.txt", "r"); |  | ||||||
|   line = NULL; |  | ||||||
|   linesize = 0; |  | ||||||
|   while (!feof(f)) { |  | ||||||
|     if (getline(&line, &linesize, f) == -1) break; |  | ||||||
|     if (sscanf(line, "%x..%x; %s", &a, &b, name) != 3) continue; |  | ||||||
|     DisplayUnicodeBlock(); |  | ||||||
|   } |  | ||||||
|   free(line); |  | ||||||
|   fclose(f); |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,212 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/assert.h" |  | ||||||
| #include "libc/calls/calls.h" |  | ||||||
| #include "libc/calls/struct/stat.h" |  | ||||||
| #include "libc/limits.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/macros.internal.h" |  | ||||||
| #include "libc/math.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.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/x/x.h" |  | ||||||
| #include "third_party/stb/stb_image.h" |  | ||||||
| 
 |  | ||||||
| #define C13(A, B)     (((A) + 3 * (B)) / 4) |  | ||||||
| #define S3T(A, B, C)  MAX(0, ((24 * (B)) - (4 * ((A) + (C)))) / 16) |  | ||||||
| #define LERP(A, B, P) ((A) * (1 - (P)) + (B) * (P)) |  | ||||||
| 
 |  | ||||||
| float ByteToFloat(int b) { |  | ||||||
|   return 1 / 255.f * b; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int FloatToByte(float f) { |  | ||||||
|   return MAX(0, MIN(255, roundf(255 * f))); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float ChessBoard(unsigned y, unsigned x, float a, float b) { |  | ||||||
|   return !((y ^ x) & (1u << 2)) ? a : b; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float AlphaBackground(unsigned y, unsigned x) { |  | ||||||
|   return ChessBoard(y, x, 1.f, .7f); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float OutOfBoundsBackground(unsigned y, unsigned x) { |  | ||||||
|   return ChessBoard(y, x, .01f, .02f); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float Opacify(size_t yn, size_t xn, const float P[yn][xn], |  | ||||||
|               const float A[yn][xn], long y, long x) { |  | ||||||
|   if ((0 <= y && y < yn) && (0 <= x && x < xn)) { |  | ||||||
|     return LERP(AlphaBackground(y, x), P[y][x], A[y][x]); |  | ||||||
|   } else { |  | ||||||
|     return OutOfBoundsBackground(y, x); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void PrintImage(size_t yn, size_t xn, float R[yn][xn], float G[yn][xn], |  | ||||||
|                 float B[yn][xn], float A[yn][xn]) { |  | ||||||
|   unsigned y, x; |  | ||||||
|   for (y = 0; y < yn; y += 2) { |  | ||||||
|     if (y) printf("\e[0m\n"); |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       printf("\e[48;2;%d;%d;%d;38;2;%d;%d;%dm▄", |  | ||||||
|              FloatToByte(Opacify(yn, xn, R, A, y + 0, x)), |  | ||||||
|              FloatToByte(Opacify(yn, xn, G, A, y + 0, x)), |  | ||||||
|              FloatToByte(Opacify(yn, xn, B, A, y + 0, x)), |  | ||||||
|              FloatToByte(Opacify(yn, xn, R, A, y + 1, x)), |  | ||||||
|              FloatToByte(Opacify(yn, xn, G, A, y + 1, x)), |  | ||||||
|              FloatToByte(Opacify(yn, xn, B, A, y + 1, x))); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   printf("\e[0m\n"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void DeblinterlaceRgba(size_t dyn, size_t dxn, float R[dyn][dxn], |  | ||||||
|                        float G[dyn][dxn], float B[dyn][dxn], float A[dyn][dxn], |  | ||||||
|                        size_t syn, size_t sxn, |  | ||||||
|                        const unsigned char src[syn][sxn][4]) { |  | ||||||
|   unsigned y, x; |  | ||||||
|   for (y = 0; y < syn; ++y) { |  | ||||||
|     for (x = 0; x < sxn; ++x) { |  | ||||||
|       R[y][x] = ByteToFloat(src[y][x][0]); |  | ||||||
|       G[y][x] = ByteToFloat(src[y][x][1]); |  | ||||||
|       B[y][x] = ByteToFloat(src[y][x][2]); |  | ||||||
|       A[y][x] = ByteToFloat(src[y][x][3]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SharpenX(size_t yw, size_t xw, float dst[yw][xw], const float src[yw][xw], |  | ||||||
|               size_t yn, size_t xn) { |  | ||||||
|   int y, x; |  | ||||||
|   for (y = 0; y < yn; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       dst[y][x] = |  | ||||||
|           S3T(src[y][MAX(0, x - 1)], src[y][x], src[y][MIN(xn - 1, x + 1)]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SharpenY(size_t yw, size_t xw, float dst[yw][xw], const float src[yw][xw], |  | ||||||
|               size_t yn, size_t xn) { |  | ||||||
|   int y, x; |  | ||||||
|   for (y = 0; y < yn; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       dst[y][x] = |  | ||||||
|           S3T(src[MAX(0, y - 1)][x], src[y][x], src[MIN(yn - 1, y + 1)][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void UpscaleX(size_t yw, size_t xw, float img[yw][xw], size_t yn, size_t xn) { |  | ||||||
|   unsigned y, x; |  | ||||||
|   for (y = yn; y--;) { |  | ||||||
|     for (x = xn; --x;) { |  | ||||||
|       img[y][x] = |  | ||||||
|           C13(img[y][MIN(xn / 2 - 1, x / 2 - 1 + x % 2 * 2)], img[y][x / 2]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void UpscaleY(size_t yw, size_t xw, float img[yw][xw], size_t yn, size_t xn) { |  | ||||||
|   unsigned y, x; |  | ||||||
|   for (y = yn; --y;) { |  | ||||||
|     for (x = xn; x--;) { |  | ||||||
|       img[y][x] = |  | ||||||
|           C13(img[MIN(yn / 2 - 1, y / 2 - 1 + y % 2 * 2)][x], img[y / 2][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Upscale(size_t yw, size_t xw, float img[yw][xw], float tmp[yw][xw], |  | ||||||
|              size_t yn, size_t xn) { |  | ||||||
|   UpscaleY(yw, xw, img, yn, xn / 2); |  | ||||||
|   SharpenY(yw, xw, tmp, img, yn, xn / 2); |  | ||||||
|   UpscaleX(yw, xw, tmp, yn, xn); |  | ||||||
|   SharpenX(yw, xw, img, tmp, yn, xn); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ProcessImageDouble(size_t yn, size_t xn, unsigned char img[yn][xn][4]) { |  | ||||||
|   void *t = xmemalign(32, sizeof(float) * yn * 2 * xn * 2); |  | ||||||
|   void *R = xmemalign(32, sizeof(float) * yn * 2 * xn * 2); |  | ||||||
|   void *G = xmemalign(32, sizeof(float) * yn * 2 * xn * 2); |  | ||||||
|   void *B = xmemalign(32, sizeof(float) * yn * 2 * xn * 2); |  | ||||||
|   void *A = xmemalign(32, sizeof(float) * yn * 2 * xn * 2); |  | ||||||
|   DeblinterlaceRgba(yn * 2, xn * 2, R, G, B, A, yn, xn, img); |  | ||||||
|   Upscale(yn * 2, xn * 2, R, t, yn * 2, xn * 2); |  | ||||||
|   Upscale(yn * 2, xn * 2, G, t, yn * 2, xn * 2); |  | ||||||
|   Upscale(yn * 2, xn * 2, B, t, yn * 2, xn * 2); |  | ||||||
|   Upscale(yn * 2, xn * 2, A, t, yn * 2, xn * 2); |  | ||||||
|   free(t); |  | ||||||
|   PrintImage(yn * 2, xn * 2, R, G, B, A); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ProcessImage(size_t yn, size_t xn, unsigned char img[yn][xn][4]) { |  | ||||||
|   void *R = xmemalign(32, sizeof(float) * yn * xn); |  | ||||||
|   void *G = xmemalign(32, sizeof(float) * yn * xn); |  | ||||||
|   void *B = xmemalign(32, sizeof(float) * yn * xn); |  | ||||||
|   void *A = xmemalign(32, sizeof(float) * yn * xn); |  | ||||||
|   DeblinterlaceRgba(yn, xn, R, G, B, A, yn, xn, img); |  | ||||||
|   PrintImage(yn, xn, R, G, B, A); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void WithImageFile(const char *path, void fn(size_t yn, size_t xn, |  | ||||||
|                                              unsigned char img[yn][xn][4])) { |  | ||||||
|   struct stat st; |  | ||||||
|   int fd, yn, xn; |  | ||||||
|   void *map, *data; |  | ||||||
|   CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path); |  | ||||||
|   CHECK_NE(-1, fstat(fd, &st)); |  | ||||||
|   CHECK_GT(st.st_size, 0); |  | ||||||
|   CHECK_LE(st.st_size, INT_MAX); |  | ||||||
|   fadvise(fd, 0, 0, MADV_WILLNEED | MADV_SEQUENTIAL); |  | ||||||
|   CHECK_NE(MAP_FAILED, |  | ||||||
|            (map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0))); |  | ||||||
|   CHECK_NOTNULL( |  | ||||||
|       (data = stbi_load_from_memory(map, st.st_size, &xn, &yn, NULL, 4)), "%s", |  | ||||||
|       path); |  | ||||||
|   CHECK_NE(-1, munmap(map, st.st_size)); |  | ||||||
|   CHECK_NE(-1, close(fd)); |  | ||||||
|   fn(yn, xn, data); |  | ||||||
|   free(data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int i; |  | ||||||
|   for (i = 1; i < argc; ++i) { |  | ||||||
|     WithImageFile(argv[i], ProcessImageDouble); |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,209 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/assert.h" |  | ||||||
| #include "libc/calls/calls.h" |  | ||||||
| #include "libc/calls/struct/stat.h" |  | ||||||
| #include "libc/limits.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/macros.internal.h" |  | ||||||
| #include "libc/math.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.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/x/x.h" |  | ||||||
| #include "third_party/stb/stb_image.h" |  | ||||||
| 
 |  | ||||||
| #define CLAMP(X)      MAX(0, MIN(255, X)) |  | ||||||
| #define C13(A, B)     (((A) + 3 * (B) + 2) >> 2) |  | ||||||
| #define S3T(A, B, C)  CLAMP(-((A) >> 2) + ((B) + ((B) >> 1)) + -((C) >> 2)) |  | ||||||
| #define LERP(X, Y, P) ((X) + (((P) * ((Y) - (X))) >> 8)) |  | ||||||
| 
 |  | ||||||
| static unsigned char ChessBoard(unsigned y, unsigned x, unsigned char a, |  | ||||||
|                                 unsigned char b) { |  | ||||||
|   return !((y ^ x) & (1u << 2)) ? a : b; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned char AlphaBackground(unsigned y, unsigned x) { |  | ||||||
|   return ChessBoard(y, x, 255, 200); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned char OutOfBoundsBackground(unsigned y, unsigned x) { |  | ||||||
|   return ChessBoard(y, x, 40, 80); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned char Opacify(size_t yn, size_t xn, |  | ||||||
|                              const unsigned char P[yn][xn], |  | ||||||
|                              const unsigned char A[yn][xn], long y, long x) { |  | ||||||
|   if ((0 <= y && y < yn) && (0 <= x && x < xn)) { |  | ||||||
|     return LERP(AlphaBackground(y, x), P[y][x], A[y][x]); |  | ||||||
|   } else { |  | ||||||
|     return OutOfBoundsBackground(y, x); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void PrintImage(size_t yn, size_t xn, unsigned char R[yn][xn], |  | ||||||
|                        unsigned char G[yn][xn], unsigned char B[yn][xn], |  | ||||||
|                        unsigned char A[yn][xn]) { |  | ||||||
|   unsigned y, x; |  | ||||||
|   for (y = 0; y < yn; y += 2) { |  | ||||||
|     if (y) printf("\e[0m\n"); |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       printf("\e[48;2;%d;%d;%d;38;2;%d;%d;%dm▄", |  | ||||||
|              Opacify(yn, xn, R, A, y + 0, x), Opacify(yn, xn, G, A, y + 0, x), |  | ||||||
|              Opacify(yn, xn, B, A, y + 0, x), Opacify(yn, xn, R, A, y + 1, x), |  | ||||||
|              Opacify(yn, xn, G, A, y + 1, x), Opacify(yn, xn, B, A, y + 1, x)); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   printf("\e[0m\n"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void DeblinterlaceRgba(size_t dyn, size_t dxn, unsigned char R[dyn][dxn], |  | ||||||
|                               unsigned char G[dyn][dxn], |  | ||||||
|                               unsigned char B[dyn][dxn], |  | ||||||
|                               unsigned char A[dyn][dxn], size_t syn, size_t sxn, |  | ||||||
|                               const unsigned char src[syn][sxn][4]) { |  | ||||||
|   unsigned y, x; |  | ||||||
|   for (y = 0; y < syn; ++y) { |  | ||||||
|     for (x = 0; x < sxn; ++x) { |  | ||||||
|       R[y][x] = src[y][x][0]; |  | ||||||
|       G[y][x] = src[y][x][1]; |  | ||||||
|       B[y][x] = src[y][x][2]; |  | ||||||
|       A[y][x] = src[y][x][3]; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void SharpenX(size_t yw, size_t xw, unsigned char dst[yw][xw], |  | ||||||
|                      const unsigned char src[yw][xw], size_t yn, size_t xn) { |  | ||||||
|   int y, x; |  | ||||||
|   for (y = 0; y < yn; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       dst[y][x] = |  | ||||||
|           S3T(src[y][MAX(0, x - 1)], src[y][x], src[y][MIN(xn - 1, x + 1)]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void SharpenY(size_t yw, size_t xw, unsigned char dst[yw][xw], |  | ||||||
|                      const unsigned char src[yw][xw], size_t yn, size_t xn) { |  | ||||||
|   int y, x; |  | ||||||
|   for (y = 0; y < yn; ++y) { |  | ||||||
|     for (x = 0; x < xn; ++x) { |  | ||||||
|       dst[y][x] = |  | ||||||
|           S3T(src[MAX(0, y - 1)][x], src[y][x], src[MIN(yn - 1, y + 1)][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void UpscaleX(size_t yw, size_t xw, unsigned char img[yw][xw], size_t yn, |  | ||||||
|                      size_t xn) { |  | ||||||
|   unsigned y, x; |  | ||||||
|   for (y = yn; y--;) { |  | ||||||
|     for (x = xn; --x;) { |  | ||||||
|       img[y][x] = |  | ||||||
|           C13(img[y][MIN(xn / 2 - 1, x / 2 - 1 + x % 2 * 2)], img[y][x / 2]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void UpscaleY(size_t yw, size_t xw, unsigned char img[yw][xw], size_t yn, |  | ||||||
|                      size_t xn) { |  | ||||||
|   unsigned y, x; |  | ||||||
|   for (y = yn; --y;) { |  | ||||||
|     for (x = xn; x--;) { |  | ||||||
|       img[y][x] = |  | ||||||
|           C13(img[MIN(yn / 2 - 1, y / 2 - 1 + y % 2 * 2)][x], img[y / 2][x]); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void Upscale(size_t yw, size_t xw, unsigned char img[yw][xw], |  | ||||||
|                     unsigned char tmp[yw][xw], size_t yn, size_t xn) { |  | ||||||
|   UpscaleY(yw, xw, img, yn, xn / 2); |  | ||||||
|   SharpenY(yw, xw, tmp, img, yn, xn / 2); |  | ||||||
|   UpscaleX(yw, xw, tmp, yn, xn); |  | ||||||
|   SharpenX(yw, xw, img, tmp, yn, xn); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void ProcessImageDouble(size_t yn, size_t xn, |  | ||||||
|                                unsigned char img[yn][xn][4]) { |  | ||||||
|   void *t = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2); |  | ||||||
|   void *R = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2); |  | ||||||
|   void *G = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2); |  | ||||||
|   void *B = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2); |  | ||||||
|   void *A = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2); |  | ||||||
|   DeblinterlaceRgba(yn * 2, xn * 2, R, G, B, A, yn, xn, img); |  | ||||||
|   Upscale(yn * 2, xn * 2, R, t, yn * 2, xn * 2); |  | ||||||
|   Upscale(yn * 2, xn * 2, G, t, yn * 2, xn * 2); |  | ||||||
|   Upscale(yn * 2, xn * 2, B, t, yn * 2, xn * 2); |  | ||||||
|   Upscale(yn * 2, xn * 2, A, t, yn * 2, xn * 2); |  | ||||||
|   free(t); |  | ||||||
|   PrintImage(yn * 2, xn * 2, R, G, B, A); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void ProcessImage(size_t yn, size_t xn, unsigned char img[yn][xn][4]) { |  | ||||||
|   void *R = xmemalign(32, sizeof(unsigned char) * yn * xn); |  | ||||||
|   void *G = xmemalign(32, sizeof(unsigned char) * yn * xn); |  | ||||||
|   void *B = xmemalign(32, sizeof(unsigned char) * yn * xn); |  | ||||||
|   void *A = xmemalign(32, sizeof(unsigned char) * yn * xn); |  | ||||||
|   DeblinterlaceRgba(yn, xn, R, G, B, A, yn, xn, img); |  | ||||||
|   PrintImage(yn, xn, R, G, B, A); |  | ||||||
|   free(R); |  | ||||||
|   free(G); |  | ||||||
|   free(B); |  | ||||||
|   free(A); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void WithImageFile(const char *path, void fn(size_t yn, size_t xn, |  | ||||||
|                                              unsigned char img[yn][xn][4])) { |  | ||||||
|   struct stat st; |  | ||||||
|   int fd, yn, xn; |  | ||||||
|   void *map, *data; |  | ||||||
|   CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path); |  | ||||||
|   CHECK_NE(-1, fstat(fd, &st)); |  | ||||||
|   CHECK_GT(st.st_size, 0); |  | ||||||
|   CHECK_LE(st.st_size, INT_MAX); |  | ||||||
|   fadvise(fd, 0, 0, MADV_WILLNEED | MADV_SEQUENTIAL); |  | ||||||
|   CHECK_NE(MAP_FAILED, |  | ||||||
|            (map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0))); |  | ||||||
|   CHECK_NOTNULL( |  | ||||||
|       (data = stbi_load_from_memory(map, st.st_size, &xn, &yn, NULL, 4)), "%s", |  | ||||||
|       path); |  | ||||||
|   CHECK_NE(-1, munmap(map, st.st_size)); |  | ||||||
|   CHECK_NE(-1, close(fd)); |  | ||||||
|   fn(yn, xn, data); |  | ||||||
|   free(data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   int i; |  | ||||||
|   for (i = 1; i < argc; ++i) { |  | ||||||
|     WithImageFile(argv[i], ProcessImageDouble); |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,85 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2022 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 "libc/calls/struct/sigaction.h" |  | ||||||
| #include "libc/calls/struct/siginfo.h" |  | ||||||
| #include "libc/calls/ucontext.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/sysv/consts/auxv.h" |  | ||||||
| #include "libc/sysv/consts/sa.h" |  | ||||||
| #include "libc/sysv/consts/sig.h" |  | ||||||
| #include "third_party/xed/x86.h" |  | ||||||
| #ifdef __x86_64__ |  | ||||||
| 
 |  | ||||||
| #define OUTPATH "vdso.elf" |  | ||||||
| 
 |  | ||||||
| volatile bool finished; |  | ||||||
| 
 |  | ||||||
| void OnSegmentationFault(int sig, siginfo_t *si, void *vctx) { |  | ||||||
|   struct XedDecodedInst xedd; |  | ||||||
|   ucontext_t *ctx = vctx; |  | ||||||
|   xed_decoded_inst_zero_set_mode(&xedd, XED_MACHINE_MODE_LONG_64); |  | ||||||
|   xed_instruction_length_decode(&xedd, (void *)ctx->uc_mcontext.rip, 15); |  | ||||||
|   ctx->uc_mcontext.rip += xedd.length; |  | ||||||
|   finished = true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   FILE *f; |  | ||||||
|   int byte; |  | ||||||
|   volatile unsigned char *vdso, *p; |  | ||||||
| 
 |  | ||||||
|   vdso = (unsigned char *)getauxval(AT_SYSINFO_EHDR); |  | ||||||
|   if (vdso) { |  | ||||||
|     fprintf(stderr, "vdso found at address %p\n", vdso); |  | ||||||
|   } else { |  | ||||||
|     fprintf(stderr, "error: AT_SYSINFO_EHDR was not in auxiliary values\n"); |  | ||||||
|     return 1; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   f = fopen(OUTPATH, "wb"); |  | ||||||
|   if (!f) { |  | ||||||
|     fprintf(stderr, "error: fopen(%`'s) failed\n", OUTPATH); |  | ||||||
|     return 1; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   struct sigaction sa = { |  | ||||||
|       .sa_sigaction = OnSegmentationFault, |  | ||||||
|       .sa_flags = SA_SIGINFO, |  | ||||||
|   }; |  | ||||||
|   sigaction(SIGSEGV, &sa, 0); |  | ||||||
|   sigaction(SIGBUS, &sa, 0); |  | ||||||
| 
 |  | ||||||
|   p = vdso; |  | ||||||
|   for (;;) { |  | ||||||
|     byte = *p++; |  | ||||||
|     if (!finished) { |  | ||||||
|       fputc(byte, f); |  | ||||||
|     } else { |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   fclose(f); |  | ||||||
|   fprintf(stderr, "%zu bytes dumped to %s\n", p - vdso, OUTPATH); |  | ||||||
| 
 |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif /* __x86_64__ */ |  | ||||||
|  | @ -1,166 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2022 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 "libc/elf/def.h" |  | ||||||
| #include "libc/elf/scalar.h" |  | ||||||
| #include "libc/elf/struct/ehdr.h" |  | ||||||
| #include "libc/elf/struct/phdr.h" |  | ||||||
| #include "libc/elf/struct/sym.h" |  | ||||||
| #include "libc/elf/struct/verdaux.h" |  | ||||||
| #include "libc/elf/struct/verdef.h" |  | ||||||
| #include "libc/intrin/kprintf.h" |  | ||||||
| #include "libc/intrin/strace.internal.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/sysv/consts/auxv.h" |  | ||||||
| 
 |  | ||||||
| static inline void PrintDsoSymbolVersions(Elf64_Verdef *vd, int sym, |  | ||||||
|                                           char *strtab) { |  | ||||||
|   Elf64_Verdaux *aux; |  | ||||||
|   for (;; vd = (Elf64_Verdef *)((char *)vd + vd->vd_next)) { |  | ||||||
|     if (!(vd->vd_flags & VER_FLG_BASE) && |  | ||||||
|         (vd->vd_ndx & 0x7fff) == (sym & 0x7fff)) { |  | ||||||
|       aux = (Elf64_Verdaux *)((char *)vd + vd->vd_aux); |  | ||||||
|       kprintf(" %s", strtab + aux->vda_name); |  | ||||||
|     } |  | ||||||
|     if (!vd->vd_next) { |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int PrintVdsoSymbols(void) { |  | ||||||
|   void *p; |  | ||||||
|   size_t i; |  | ||||||
|   Elf64_Ehdr *ehdr; |  | ||||||
|   Elf64_Phdr *phdr; |  | ||||||
|   char *strtab = 0; |  | ||||||
|   size_t *dyn, base; |  | ||||||
|   unsigned long *ap; |  | ||||||
|   Elf64_Sym *symtab = 0; |  | ||||||
|   uint16_t *versym = 0; |  | ||||||
|   Elf_Symndx *hashtab = 0; |  | ||||||
|   Elf64_Verdef *verdef = 0; |  | ||||||
|   const char *typename, *bindname; |  | ||||||
| 
 |  | ||||||
|   for (ehdr = 0, ap = __auxv; ap[0]; ap += 2) { |  | ||||||
|     if (ap[0] == AT_SYSINFO_EHDR) { |  | ||||||
|       ehdr = (void *)ap[1]; |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (!ehdr) { |  | ||||||
|     kprintf("error: AT_SYSINFO_EHDR not found\n"); |  | ||||||
|     return 1; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   phdr = (void *)((char *)ehdr + ehdr->e_phoff); |  | ||||||
|   for (base = -1, dyn = 0, i = 0; i < ehdr->e_phnum; |  | ||||||
|        i++, phdr = (void *)((char *)phdr + ehdr->e_phentsize)) { |  | ||||||
|     switch (phdr->p_type) { |  | ||||||
|       case PT_LOAD: |  | ||||||
|         // modern linux uses the base address zero, but elders
 |  | ||||||
|         // e.g. rhel7 uses the base address 0xffffffffff700000
 |  | ||||||
|         base = (size_t)ehdr + phdr->p_offset - phdr->p_vaddr; |  | ||||||
|         break; |  | ||||||
|       case PT_DYNAMIC: |  | ||||||
|         dyn = (void *)((char *)ehdr + phdr->p_offset); |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (!dyn || base == -1) { |  | ||||||
|     kprintf("error: missing program headers\n"); |  | ||||||
|     return 2; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   for (i = 0; dyn[i]; i += 2) { |  | ||||||
|     p = (void *)(base + dyn[i + 1]); |  | ||||||
|     switch (dyn[i]) { |  | ||||||
|       case DT_STRTAB: |  | ||||||
|         strtab = p; |  | ||||||
|         break; |  | ||||||
|       case DT_SYMTAB: |  | ||||||
|         symtab = p; |  | ||||||
|         break; |  | ||||||
|       case DT_HASH: |  | ||||||
|         hashtab = p; |  | ||||||
|         break; |  | ||||||
|       case DT_VERSYM: |  | ||||||
|         versym = p; |  | ||||||
|         break; |  | ||||||
|       case DT_VERDEF: |  | ||||||
|         verdef = p; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (!verdef) { |  | ||||||
|     versym = 0; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   if (!strtab || !symtab || !hashtab) { |  | ||||||
|     kprintf("error: strtab/symtab/hashtab not found\n"); |  | ||||||
|     return 3; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   for (i = 0; i < hashtab[1]; i++) { |  | ||||||
|     if (!symtab[i].st_shndx) { |  | ||||||
|       continue; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     switch (ELF64_ST_BIND(symtab[i].st_info)) { |  | ||||||
|       case STB_LOCAL: |  | ||||||
|         bindname = "locl"; |  | ||||||
|         break; |  | ||||||
|       case STB_GLOBAL: |  | ||||||
|         bindname = "glob"; |  | ||||||
|         break; |  | ||||||
|       case STB_WEAK: |  | ||||||
|         bindname = "weak"; |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         bindname = "????"; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     switch (ELF64_ST_TYPE(symtab[i].st_info)) { |  | ||||||
|       case STT_FUNC: |  | ||||||
|         typename = "func"; |  | ||||||
|         break; |  | ||||||
|       case STT_OBJECT: |  | ||||||
|         typename = " obj"; |  | ||||||
|         break; |  | ||||||
|       case STT_NOTYPE: |  | ||||||
|         typename = "none"; |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         typename = "????"; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     kprintf("%s %s %-40s", bindname, typename, strtab + symtab[i].st_name); |  | ||||||
|     PrintDsoSymbolVersions(verdef, versym[i], strtab); |  | ||||||
|     kprintf("\n"); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   return PrintVdsoSymbols(); |  | ||||||
| } |  | ||||||
|  | @ -1,97 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "libc/assert.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| 
 |  | ||||||
| #define DIST(X, Y)   ((X) - (Y)) |  | ||||||
| #define SQR(X)       ((X) * (X)) |  | ||||||
| #define SUM(X, Y, Z) ((X) + (Y) + (Z)) |  | ||||||
| 
 |  | ||||||
| static const uint8_t kXtermCube[] = {0, 0137, 0207, 0257, 0327, 0377}; |  | ||||||
| 
 |  | ||||||
| static int uncube(int x) { |  | ||||||
|   return x < 48 ? 0 : x < 115 ? 1 : (x - 35) / 40; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int rgb2xterm256(int r, int g, int b) { |  | ||||||
|   unsigned av, ir, ig, ib, il, qr, qg, qb, ql; |  | ||||||
|   av = (r + g + b) / 3; |  | ||||||
|   ql = (il = av > 238 ? 23 : (av - 3) / 10) * 10 + 8; |  | ||||||
|   qr = kXtermCube[(ir = uncube(r))]; |  | ||||||
|   qg = kXtermCube[(ig = uncube(g))]; |  | ||||||
|   qb = kXtermCube[(ib = uncube(b))]; |  | ||||||
|   if (SUM(SQR(DIST(qr, r)), SQR(DIST(qg, g)), SQR(DIST(qb, b))) <= |  | ||||||
|       SUM(SQR(DIST(ql, r)), SQR(DIST(ql, g)), SQR(DIST(ql, b)))) { |  | ||||||
|     return ir * 36 + ig * 6 + ib + 020; |  | ||||||
|   } else { |  | ||||||
|     return il + 0350; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool IsUglyColorMixture(int rune, int y, int tone, bool toneisfg) { |  | ||||||
|   assert(tone == 16 || (231 <= tone && tone <= 255)); |  | ||||||
|   return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   unsigned y, z, x, k, w; |  | ||||||
|   static const char16_t s[2][3] = {{u'▓', u'▒', u'░'}, {u'░', u'▒', u'▓'}}; |  | ||||||
| 
 |  | ||||||
|   printf("\npure\n"); |  | ||||||
|   for (y = 0; y < 6; ++y) { |  | ||||||
|     for (z = 0; z < 6; ++z) { |  | ||||||
|       for (x = 0; x < 6; ++x) { |  | ||||||
|         printf("\033[48;5;%hhum  ", 16 + x + y * 6 + z * 6 * 6); |  | ||||||
|       } |  | ||||||
|       printf("\033[0m "); |  | ||||||
|     } |  | ||||||
|     printf("\n"); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| #define MIX(NAME, COLOR)                                                       \ |  | ||||||
|   do {                                                                         \ |  | ||||||
|     printf("\n%s %d ▓░/▒▒/░▓\n", NAME, COLOR);                                 \ |  | ||||||
|     for (k = 0; k < 3; ++k) {                                                  \ |  | ||||||
|       for (y = 0; y < 6; ++y) {                                                \ |  | ||||||
|         for (z = 0; z < 6; ++z) {                                              \ |  | ||||||
|           for (x = 0; x < 6; ++x) {                                            \ |  | ||||||
|             printf("\033[48;5;%hhu;38;5;%hhum%lc", COLOR,                      \ |  | ||||||
|                    16 + x + y * 6 + z * 6 * 6, s[0][k]);                       \ |  | ||||||
|             printf("\033[48;5;%hhu;38;5;%hhum%lc", 16 + x + y * 6 + z * 6 * 6, \ |  | ||||||
|                    COLOR, s[1][k]);                                            \ |  | ||||||
|           }                                                                    \ |  | ||||||
|           printf("\033[0m ");                                                  \ |  | ||||||
|         }                                                                      \ |  | ||||||
|         printf("\n");                                                          \ |  | ||||||
|       }                                                                        \ |  | ||||||
|     }                                                                          \ |  | ||||||
|   } while (0) |  | ||||||
| 
 |  | ||||||
|   MIX("tint", 231); |  | ||||||
|   MIX("tint", 255); |  | ||||||
|   MIX("tint", 254); |  | ||||||
|   MIX("tone", 240); |  | ||||||
|   MIX("shade", 232); |  | ||||||
| 
 |  | ||||||
|   for (w = 233; w < 254; ++w) { |  | ||||||
|     MIX("gray", w); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,183 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "dsp/tty/quant.h" |  | ||||||
| #include "libc/fmt/fmt.h" |  | ||||||
| #include "libc/intrin/bits.h" |  | ||||||
| #include "libc/intrin/xchg.internal.h" |  | ||||||
| #include "libc/math.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| 
 |  | ||||||
| /* #define ROUND(x) x */ |  | ||||||
| /* #define RT       int */ |  | ||||||
| /* #define R1       1 */ |  | ||||||
| /* #define R2       2 */ |  | ||||||
| /* #define R3       3 */ |  | ||||||
| 
 |  | ||||||
| #define RT        float |  | ||||||
| #define MUL(x, y) ((x) * (y)) |  | ||||||
| #define RND(x)    roundf(x) |  | ||||||
| #define R1        0.25f |  | ||||||
| #define R2        0.50f |  | ||||||
| #define R3        0.75f |  | ||||||
| 
 |  | ||||||
| #define rgb_t struct TtyRgb |  | ||||||
| 
 |  | ||||||
| forceinline RT lerp(RT x, RT y, RT d) { |  | ||||||
|   return x * (1.0 - d) + y * d; |  | ||||||
| } |  | ||||||
| forceinline int lerp255(RT x, RT y, RT d) { |  | ||||||
|   return lerp(x / 255.0, y / 255.0, d) * 255.0; |  | ||||||
| } |  | ||||||
| forceinline rgb_t rgblerp(rgb_t x, rgb_t y, RT d) { |  | ||||||
|   return (rgb_t){lerp255(x.r, y.r, d), lerp255(x.g, y.g, d), |  | ||||||
|                  lerp255(x.b, y.b, d)}; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| forceinline rgb_t getquant(unsigned xt) { |  | ||||||
|   return g_ansi2rgb_[xt]; |  | ||||||
| } |  | ||||||
| forceinline unsigned dist(int x, int y) { |  | ||||||
|   return x - y; |  | ||||||
| } |  | ||||||
| forceinline unsigned sqr(int x) { |  | ||||||
|   return x * x; |  | ||||||
| } |  | ||||||
| forceinline unsigned rgbdist(rgb_t x, rgb_t y) { |  | ||||||
|   return sqrt(sqr(dist(x.r, y.r)) + sqr(dist(x.g, y.g)) + sqr(dist(x.b, y.b))); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool b; |  | ||||||
| rgb_t rgb, cc, c1, c2; |  | ||||||
| unsigned i, j, k, m, n, x, y; |  | ||||||
| char buf[128]; |  | ||||||
| 
 |  | ||||||
| /* 0125 025 067-29   # '░' bg=0352 fg=0306 → ░░░ */ |  | ||||||
| /* 0125 025 067-29   # '▓' bg=0306 fg=0352 → ▓▓▓ */ |  | ||||||
| /* 0125 055 067-29   # '░' bg=0352 fg=0314 → ░░░ */ |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   /* memcpy(g_ansi2rgb_, &kTangoPalette, sizeof(kTangoPalette)); */ |  | ||||||
|   /* i = 21; */ |  | ||||||
|   /* j = 22; */ |  | ||||||
|   /* c1 = getquant(i); */ |  | ||||||
|   /* c2 = getquant(j); */ |  | ||||||
|   /* cc = rgblerp(c1, c2, R1); */ |  | ||||||
|   /* printf("rgblerp((%3d,%3d,%3d), (%3d,%3d,%3d),4) → (%3d,%3d,%3d)\n", c1.r,
 |  | ||||||
|    */ |  | ||||||
|   /*        c1.g, c1.b, c2.r, c2.g, c2.b, cc.r, cc.g, cc.b); */ |  | ||||||
|   /* exit(0); */ |  | ||||||
| 
 |  | ||||||
|   for (m = 16; m < 256; m += 6) { |  | ||||||
|     for (n = 16; n < 256; n += 6) { |  | ||||||
|       printf("------------------------------------------------------------\n"); |  | ||||||
|       i = m; |  | ||||||
|       j = n; |  | ||||||
|       b = false; |  | ||||||
|       while (i < m + 6) { |  | ||||||
|         printf("\n"); |  | ||||||
| 
 |  | ||||||
|         cc = getquant(i); |  | ||||||
|         sprintf(buf, "\e[48;5;%dm   ", i); |  | ||||||
|         printf("0x%02x%02x%02x, %d,%d,0\t/* 0x%02x%02x%02x           " |  | ||||||
|                " + ' ' bg=%3d        → %s         \e[0m */\n", |  | ||||||
|                cc.b, cc.g, cc.r, i, 0, getquant(i).r, getquant(i).g, |  | ||||||
|                getquant(i).b, i, buf); |  | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
|         sprintf(buf, "\e[38;5;%dm███", i); |  | ||||||
|         printf("0x%08x 0x%02x%02x%02x\t" |  | ||||||
|                " '█'        fg=%3d → %s\e[0m\n", |  | ||||||
|                cc.b, cc.g, cc.r, strlen(buf), i, buf); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|         for (x = i; x < i + 1; ++x) { |  | ||||||
|           for (y = j; y < j + 1; ++y) { |  | ||||||
|             for (k = 0; k < 2; ++k) { |  | ||||||
|               if (x > y /*  && */ |  | ||||||
|                   /* rgbdist(getquant(x), getquant(y)) < 49744125 / 16 */ /*  &&
 |  | ||||||
|                   ((32 |  | ||||||
|                   <= x && x <= 232) && (32 <= y && y <= 232)) |  | ||||||
|                   && */ |  | ||||||
|                   /* (cc.r > 0137 && cc.g > 0137 && cc.b > 0137) */) { |  | ||||||
|                 sprintf(buf, "\e[48;5;%d;38;5;%dm░░░", x, y); |  | ||||||
|                 cc = rgblerp(getquant(x), getquant(y), R1); |  | ||||||
|                 printf("0x%02x%02x%02x, %d,%d,1\t/* 0x%02x%02x%02x + " |  | ||||||
|                        "0x%02x%02x%02x" |  | ||||||
|                        " + '░' bg=%3d fg=%3d → " |  | ||||||
|                        "\e[48;5;%dm   \e[48;5;%dm   " |  | ||||||
|                        "%s\e[48;2;%d;%d;%dm   \e[0m */\n", |  | ||||||
|                        cc.b, cc.g, cc.r, x, y, getquant(x).r, getquant(x).g, |  | ||||||
|                        getquant(x).b, getquant(y).r, getquant(y).g, |  | ||||||
|                        getquant(y).b, x, y, x, y, buf, cc.r, cc.g, cc.b); |  | ||||||
| 
 |  | ||||||
|                 sprintf(buf, "\e[48;5;%d;38;5;%dm▒▒▒", x, y); |  | ||||||
|                 cc = rgblerp(getquant(x), getquant(y), R2); |  | ||||||
|                 printf("0x%02x%02x%02x, %d,%d,2\t/* 0x%02x%02x%02x + " |  | ||||||
|                        "0x%02x%02x%02x" |  | ||||||
|                        " + '▒' bg=%3d fg=%3d → " |  | ||||||
|                        "\e[48;5;%dm   \e[48;5;%dm   " |  | ||||||
|                        "%s\e[48;2;%d;%d;%dm   \e[0m */\n", |  | ||||||
|                        cc.b, cc.g, cc.r, x, y, getquant(x).r, getquant(x).g, |  | ||||||
|                        getquant(x).b, getquant(y).r, getquant(y).g, |  | ||||||
|                        getquant(y).b, x, y, x, y, buf, cc.r, cc.g, cc.b); |  | ||||||
| 
 |  | ||||||
|                 sprintf(buf, "\e[48;5;%d;38;5;%dm▓▓▓", x, y); |  | ||||||
|                 cc = rgblerp(getquant(x), getquant(y), R3); |  | ||||||
|                 printf("0x%02x%02x%02x, %d,%d,3\t/* 0x%02x%02x%02x + " |  | ||||||
|                        "0x%02x%02x%02x" |  | ||||||
|                        " + '▓' bg=%3d fg=%3d → " |  | ||||||
|                        "\e[48;5;%dm   \e[48;5;%dm   " |  | ||||||
|                        "%s\e[48;2;%d;%d;%dm   \e[0m */\n", |  | ||||||
|                        cc.b, cc.g, cc.r, x, y, getquant(x).r, getquant(x).g, |  | ||||||
|                        getquant(x).b, getquant(y).r, getquant(y).g, |  | ||||||
|                        getquant(y).b, x, y, x, y, buf, cc.r, cc.g, cc.b); |  | ||||||
|               } |  | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
|               sprintf(buf, "\e[48;5;%d;38;5;%dm▓▓▓", x, y); |  | ||||||
|               cc = rgblerp((c1 = getquant(x)), (c2 = getquant(y)), R3); |  | ||||||
|               printf("0%03o%03o%03o\t# '▓' bg=%3d fg=%3d → " |  | ||||||
|                      "%s\e[48;2;%d;%d;%dm   \e[0m\n", |  | ||||||
|                      cc.b, cc.g, cc.r, strlen(buf), x, y, buf, |  | ||||||
|                      lerp255(c1.r, c2.r, R3), lerp255(c1.g, c2.g, R3), |  | ||||||
|                      lerp255(c1.b, c2.b, R3)); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|               xchg(&x, &y); |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         ++i; |  | ||||||
|         ++j; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   /* for (i = 0; i < 255; ++i) { */ |  | ||||||
|   /*   for (j = 0; j < 255; ++j) { */ |  | ||||||
|   /*     for (k = 0; k < 255; ++k) { */ |  | ||||||
|   /*       printf("0%03o%03o%03o\n", i, j, k); */ |  | ||||||
|   /*     } */ |  | ||||||
|   /*   } */ |  | ||||||
|   /* } */ |  | ||||||
| 
 |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,186 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "dsp/tty/quant.h" |  | ||||||
| #include "libc/fmt/fmt.h" |  | ||||||
| #include "libc/log/check.h" |  | ||||||
| #include "libc/macros.internal.h" |  | ||||||
| #include "libc/math.h" |  | ||||||
| #include "libc/mem/mem.h" |  | ||||||
| #include "libc/runtime/runtime.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| #include "libc/sysv/consts/ex.h" |  | ||||||
| #include "libc/sysv/consts/exit.h" |  | ||||||
| #include "third_party/getopt/getopt.internal.h" |  | ||||||
| 
 |  | ||||||
| #define USAGE \ |  | ||||||
|   " [FLAGS] [PATH...]\n\
 |  | ||||||
| \n\ |  | ||||||
| Flags:\n\ |  | ||||||
|   -o PATH    output path\n\ |  | ||||||
|   -h         shows this information\n\ |  | ||||||
| \n" |  | ||||||
| 
 |  | ||||||
| static size_t linecap_; |  | ||||||
| static FILE *in_, *out_; |  | ||||||
| static char *inpath_, *outpath_, *line_; |  | ||||||
| 
 |  | ||||||
| void PrintUsage(int rc, FILE *f) { |  | ||||||
|   fputs("Usage: ", f); |  | ||||||
|   fputs(program_invocation_name, f); |  | ||||||
|   fputs(USAGE, f); |  | ||||||
|   exit(rc); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GetOpts(int *argc, char *argv[]) { |  | ||||||
|   int opt; |  | ||||||
|   outpath_ = "-"; |  | ||||||
|   while ((opt = getopt(*argc, argv, "?ho:")) != -1) { |  | ||||||
|     switch (opt) { |  | ||||||
|       case 'o': |  | ||||||
|         outpath_ = optarg; |  | ||||||
|         break; |  | ||||||
|       case '?': |  | ||||||
|       case 'h': |  | ||||||
|         PrintUsage(EXIT_SUCCESS, stdout); |  | ||||||
|       default: |  | ||||||
|         PrintUsage(EX_USAGE, stderr); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   if (optind == *argc) { |  | ||||||
|     argv[(*argc)++] = "-"; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #define U256F1(X) ((float)((X)&0xffu) * 256.0f) |  | ||||||
| #define F1U256(X) MAX(MIN((int)rintl(roundl(256.0f * (X))), 255), 0) |  | ||||||
| 
 |  | ||||||
| forceinline struct TtyRgb getquant(unsigned xt) { |  | ||||||
|   return g_ansi2rgb_[xt]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| forceinline unsigned dist(int x, int y) { |  | ||||||
|   return x - y; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| forceinline unsigned sqr(int x) { |  | ||||||
|   return x * x; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned rgb2hsl(unsigned rgba) { |  | ||||||
|   /* this is broken */ |  | ||||||
|   unsigned h8, s8, l8; |  | ||||||
|   float r, g, b, h, s, d, l, cmax, cmin; |  | ||||||
|   r = U256F1(rgba); |  | ||||||
|   g = U256F1(rgba >> 010); |  | ||||||
|   b = U256F1(rgba >> 020); |  | ||||||
|   cmax = MAX(MAX(r, g), b); |  | ||||||
|   cmin = MIN(MIN(r, g), b); |  | ||||||
|   h = 0.0f; |  | ||||||
|   s = 0.0f; |  | ||||||
|   d = cmax - cmin; |  | ||||||
|   l = (cmax + cmin) / 2.0f; |  | ||||||
|   if (cmax != cmin) { |  | ||||||
|     s = l > 0.5L ? d / (2.0f - cmax - cmin) : d / (cmax + cmin); |  | ||||||
|     if (cmax == r) { |  | ||||||
|       h = (g - b) / d + (g < b ? 6.0f : 0.0f); |  | ||||||
|     } else if (cmax == g) { |  | ||||||
|       h = (b - r) / d + 2.0f; |  | ||||||
|     } else if (cmax == b) { |  | ||||||
|       h = (r - g) / d + 4.0f; |  | ||||||
|     } |  | ||||||
|     h /= 6.0f; |  | ||||||
|   } |  | ||||||
|   h8 = F1U256(h); |  | ||||||
|   s8 = F1U256(s); |  | ||||||
|   l8 = F1U256(l); |  | ||||||
|   return ((rgba >> 030) & 255) << 030 | l8 << 020 | s8 << 010 | h8; |  | ||||||
| } |  | ||||||
| static struct TtyRgb rgb2hsl2(struct TtyRgb rgb) { |  | ||||||
|   unsigned x = |  | ||||||
|       (unsigned)rgb.b << 020 | (unsigned)rgb.g << 010 | (unsigned)rgb.r; |  | ||||||
|   unsigned y = rgb2hsl(x); |  | ||||||
|   return (struct TtyRgb){ |  | ||||||
|       .r = y & 0xff, .g = (y >> 010) & 0xff, .b = (y >> 020) & 0xff}; |  | ||||||
| } |  | ||||||
| static unsigned rgbdist(struct TtyRgb x, struct TtyRgb y) { |  | ||||||
|   x = rgb2hsl2(x); |  | ||||||
|   y = rgb2hsl2(y); |  | ||||||
|   return sqrt(sqr(dist(x.r, y.r)) + sqr(dist(x.g, y.g)) + sqr(dist(x.b, y.b))); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned xtdist(unsigned x, unsigned y) { |  | ||||||
|   return rgbdist(getquant(x), getquant(y)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Show(unsigned color, unsigned bg, unsigned fg, unsigned glyph) { |  | ||||||
|   uint8_t r, g, b; |  | ||||||
|   b = (color >> 020) & 0xff; |  | ||||||
|   g = (color >> 010) & 0xff; |  | ||||||
|   r = color & 0xff; |  | ||||||
|   printf("\tmix\t0x%04x,%3d,%3d,%3d,%3d,%3d,%3d\t# \e[48;2;%d;%d;%dm   \e[0m\n", |  | ||||||
|          rgbdist((struct TtyRgb){r, g, b, 0}, (struct TtyRgb){0, 0, 0, 0}), r, |  | ||||||
|          g, b, bg, fg, glyph, r, g, b); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ProcessFile(void) { |  | ||||||
|   char *p; |  | ||||||
|   unsigned color1, bg1, fg1, glyph1; |  | ||||||
|   unsigned color, bg, fg, glyph; |  | ||||||
|   color1 = -1u; |  | ||||||
|   bg1 = -1u; |  | ||||||
|   fg1 = -1u; |  | ||||||
|   glyph1 = -1u; |  | ||||||
|   while ((getline(&line_, &linecap_, in_)) != -1) { |  | ||||||
|     p = _chomp(line_); |  | ||||||
|     sscanf(p, "%x, %u,%u,%u", &color, &bg, &fg, &glyph); |  | ||||||
|     if (color != color1) { |  | ||||||
|       if (color1 != -1u) { |  | ||||||
|         Show(color1, bg1, fg1, glyph1); |  | ||||||
|       } |  | ||||||
|       color1 = color; |  | ||||||
|       bg1 = bg; |  | ||||||
|       fg1 = fg; |  | ||||||
|       glyph1 = glyph; |  | ||||||
|     } |  | ||||||
|     if ((fg1 && !fg) || (fg && fg1 && xtdist(fg, bg) < xtdist(fg1, bg1))) { |  | ||||||
|       color1 = color; |  | ||||||
|       bg1 = bg; |  | ||||||
|       fg1 = fg; |  | ||||||
|       glyph1 = glyph; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   Show(color1, bg1, fg1, glyph1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   size_t i; |  | ||||||
|   GetOpts(&argc, argv); |  | ||||||
|   CHECK_NOTNULL((out_ = fopen(outpath_, "w"))); |  | ||||||
|   for (i = optind; i < argc; ++i) { |  | ||||||
|     CHECK_NOTNULL((in_ = fopen((inpath_ = argv[i]), "r"))); |  | ||||||
|     ProcessFile(); |  | ||||||
|     CHECK_NE(-1, fclose(in_)); |  | ||||||
|     in_ = 0; |  | ||||||
|   } |  | ||||||
|   CHECK_NE(-1, fclose(out_)); |  | ||||||
|   out_ = 0; |  | ||||||
|   free(line_); |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,77 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2021 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 "libc/math.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| 
 |  | ||||||
| #define N 8 |  | ||||||
| 
 |  | ||||||
| #define SQR(X) ((X) * (X)) |  | ||||||
| 
 |  | ||||||
| static const uint8_t kXtermCube[6] = {0, 0137, 0207, 0257, 0327, 0377}; |  | ||||||
| 
 |  | ||||||
| static int rgb2xterm256(int r, int g, int b) { |  | ||||||
|   int cerr, gerr, ir, ig, ib, gray, grai, cr, cg, cb, gv; |  | ||||||
|   gray = round(r * .299 + g * .587 + b * .114); |  | ||||||
|   grai = gray > 238 ? 23 : (gray - 3) / 10; |  | ||||||
|   ir = r < 48 ? 0 : r < 115 ? 1 : (r - 35) / 40; |  | ||||||
|   ig = g < 48 ? 0 : g < 115 ? 1 : (g - 35) / 40; |  | ||||||
|   ib = b < 48 ? 0 : b < 115 ? 1 : (b - 35) / 40; |  | ||||||
|   cr = kXtermCube[ir]; |  | ||||||
|   cg = kXtermCube[ig]; |  | ||||||
|   cb = kXtermCube[ib]; |  | ||||||
|   gv = 8 + 10 * grai; |  | ||||||
|   cerr = SQR(cr - r) + SQR(cg - g) + SQR(cb - b); |  | ||||||
|   gerr = SQR(gv - r) + SQR(gv - g) + SQR(gv - b); |  | ||||||
|   if (cerr <= gerr) { |  | ||||||
|     return 16 + 36 * ir + 6 * ig + ib; |  | ||||||
|   } else { |  | ||||||
|     return 232 + grai; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   double d; |  | ||||||
|   int i, j, x; |  | ||||||
|   int r, g, b; |  | ||||||
|   double G[N][3]; |  | ||||||
|   double rgb[2][3] = { |  | ||||||
|       {1, 0, 0}, |  | ||||||
|       {0, 1, 0}, |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   for (i = 0; i < N; ++i) { |  | ||||||
|     for (j = 0; j < 3; ++j) { |  | ||||||
|       d = (rgb[1][j] - rgb[0][j]) / (N - 1); |  | ||||||
|       G[i][j] = rgb[0][j] + d * i; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   for (i = 0; i < N; ++i) { |  | ||||||
|     r = round(G[i][0] * 255); |  | ||||||
|     g = round(G[i][1] * 255); |  | ||||||
|     b = round(G[i][2] * 255); |  | ||||||
|     x = rgb2xterm256(r, g, b); |  | ||||||
|     printf("\e[38;5;232;48;5;%dmabcdefg       \e[0m %3d " |  | ||||||
|            "\e[38;5;232;48;2;%d;%d;%dmabcdgefg      \e[0m " |  | ||||||
|            "%3d %3d %3d %f %f %f\n", |  | ||||||
|            x, x, r, g, b, r, g, b, G[i][0], G[i][1], G[i][2]); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  | @ -1,706 +0,0 @@ | ||||||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 |  | ||||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ |  | ||||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ |  | ||||||
| │ Copyright 2020 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 "dsp/tty/xtermname.h" |  | ||||||
| #include "libc/stdio/stdio.h" |  | ||||||
| #include "libc/str/str.h" |  | ||||||
| 
 |  | ||||||
| struct Rgb { |  | ||||||
|   uint8_t r, g, b; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const struct Rgb kTango[16] = { |  | ||||||
|     {0x00, 0x00, 0x00}, {0x80, 0x00, 0x00}, {0x00, 0x80, 0x00}, |  | ||||||
|     {0x80, 0x80, 0x00}, {0x00, 0x00, 0x80}, {0x80, 0x00, 0x80}, |  | ||||||
|     {0x00, 0x80, 0x80}, {0xc0, 0xc0, 0xc0}, {0x80, 0x80, 0x80}, |  | ||||||
|     {0xff, 0x00, 0x00}, {0x00, 0xff, 0x00}, {0xff, 0xff, 0x00}, |  | ||||||
|     {0x00, 0x00, 0xff}, {0xff, 0x00, 0xff}, {0x00, 0xff, 0xff}, |  | ||||||
|     {0xff, 0xff, 0xff}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const struct Rgb kXtermRgb[] = { |  | ||||||
|     /* 0..15: ansi 16-color palette */ |  | ||||||
|     {0x00, 0x00, 0x00}, |  | ||||||
|     {0x80, 0x00, 0x00}, |  | ||||||
|     {0x00, 0x80, 0x00}, |  | ||||||
|     {0x80, 0x80, 0x00}, |  | ||||||
|     {0x00, 0x00, 0x80}, |  | ||||||
|     {0x80, 0x00, 0x80}, |  | ||||||
|     {0x00, 0x80, 0x80}, |  | ||||||
|     {0xc0, 0xc0, 0xc0}, |  | ||||||
|     {0x80, 0x80, 0x80}, |  | ||||||
|     {0xff, 0x00, 0x00}, |  | ||||||
|     {0x00, 0xff, 0x00}, |  | ||||||
|     {0xff, 0xff, 0x00}, |  | ||||||
|     {0x00, 0x00, 0xff}, |  | ||||||
|     {0xff, 0x00, 0xff}, |  | ||||||
|     {0x00, 0xff, 0xff}, |  | ||||||
|     {0xff, 0xff, 0xff}, |  | ||||||
| 
 |  | ||||||
|     /* 16..231: xterm256 color cubes */ |  | ||||||
|     {0x00, 0x00, 0x00}, |  | ||||||
|     {0x00, 0x00, 0x5f}, |  | ||||||
|     {0x00, 0x00, 0x87}, |  | ||||||
|     {0x00, 0x00, 0xaf}, |  | ||||||
|     {0x00, 0x00, 0xd7}, |  | ||||||
|     {0x00, 0x00, 0xff}, |  | ||||||
|     {0x00, 0x5f, 0x00}, |  | ||||||
|     {0x00, 0x5f, 0x5f}, |  | ||||||
|     {0x00, 0x5f, 0x87}, |  | ||||||
|     {0x00, 0x5f, 0xaf}, |  | ||||||
|     {0x00, 0x5f, 0xd7}, |  | ||||||
|     {0x00, 0x5f, 0xff}, |  | ||||||
|     {0x00, 0x87, 0x00}, |  | ||||||
|     {0x00, 0x87, 0x5f}, |  | ||||||
|     {0x00, 0x87, 0x87}, |  | ||||||
|     {0x00, 0x87, 0xaf}, |  | ||||||
|     {0x00, 0x87, 0xd7}, |  | ||||||
|     {0x00, 0x87, 0xff}, |  | ||||||
|     {0x00, 0xaf, 0x00}, |  | ||||||
|     {0x00, 0xaf, 0x5f}, |  | ||||||
|     {0x00, 0xaf, 0x87}, |  | ||||||
|     {0x00, 0xaf, 0xaf}, |  | ||||||
|     {0x00, 0xaf, 0xd7}, |  | ||||||
|     {0x00, 0xaf, 0xff}, |  | ||||||
|     {0x00, 0xd7, 0x00}, |  | ||||||
|     {0x00, 0xd7, 0x5f}, |  | ||||||
|     {0x00, 0xd7, 0x87}, |  | ||||||
|     {0x00, 0xd7, 0xaf}, |  | ||||||
|     {0x00, 0xd7, 0xd7}, |  | ||||||
|     {0x00, 0xd7, 0xff}, |  | ||||||
|     {0x00, 0xff, 0x00}, |  | ||||||
|     {0x00, 0xff, 0x5f}, |  | ||||||
|     {0x00, 0xff, 0x87}, |  | ||||||
|     {0x00, 0xff, 0xaf}, |  | ||||||
|     {0x00, 0xff, 0xd7}, |  | ||||||
|     {0x00, 0xff, 0xff}, |  | ||||||
|     {0x5f, 0x00, 0x00}, |  | ||||||
|     {0x5f, 0x00, 0x5f}, |  | ||||||
|     {0x5f, 0x00, 0x87}, |  | ||||||
|     {0x5f, 0x00, 0xaf}, |  | ||||||
|     {0x5f, 0x00, 0xd7}, |  | ||||||
|     {0x5f, 0x00, 0xff}, |  | ||||||
|     {0x5f, 0x5f, 0x00}, |  | ||||||
|     {0x5f, 0x5f, 0x5f}, |  | ||||||
|     {0x5f, 0x5f, 0x87}, |  | ||||||
|     {0x5f, 0x5f, 0xaf}, |  | ||||||
|     {0x5f, 0x5f, 0xd7}, |  | ||||||
|     {0x5f, 0x5f, 0xff}, |  | ||||||
|     {0x5f, 0x87, 0x00}, |  | ||||||
|     {0x5f, 0x87, 0x5f}, |  | ||||||
|     {0x5f, 0x87, 0x87}, |  | ||||||
|     {0x5f, 0x87, 0xaf}, |  | ||||||
|     {0x5f, 0x87, 0xd7}, |  | ||||||
|     {0x5f, 0x87, 0xff}, |  | ||||||
|     {0x5f, 0xaf, 0x00}, |  | ||||||
|     {0x5f, 0xaf, 0x5f}, |  | ||||||
|     {0x5f, 0xaf, 0x87}, |  | ||||||
|     {0x5f, 0xaf, 0xaf}, |  | ||||||
|     {0x5f, 0xaf, 0xd7}, |  | ||||||
|     {0x5f, 0xaf, 0xff}, |  | ||||||
|     {0x5f, 0xd7, 0x00}, |  | ||||||
|     {0x5f, 0xd7, 0x5f}, |  | ||||||
|     {0x5f, 0xd7, 0x87}, |  | ||||||
|     {0x5f, 0xd7, 0xaf}, |  | ||||||
|     {0x5f, 0xd7, 0xd7}, |  | ||||||
|     {0x5f, 0xd7, 0xff}, |  | ||||||
|     {0x5f, 0xff, 0x00}, |  | ||||||
|     {0x5f, 0xff, 0x5f}, |  | ||||||
|     {0x5f, 0xff, 0x87}, |  | ||||||
|     {0x5f, 0xff, 0xaf}, |  | ||||||
|     {0x5f, 0xff, 0xd7}, |  | ||||||
|     {0x5f, 0xff, 0xff}, |  | ||||||
|     {0x87, 0x00, 0x00}, |  | ||||||
|     {0x87, 0x00, 0x5f}, |  | ||||||
|     {0x87, 0x00, 0x87}, |  | ||||||
|     {0x87, 0x00, 0xaf}, |  | ||||||
|     {0x87, 0x00, 0xd7}, |  | ||||||
|     {0x87, 0x00, 0xff}, |  | ||||||
|     {0x87, 0x5f, 0x00}, |  | ||||||
|     {0x87, 0x5f, 0x5f}, |  | ||||||
|     {0x87, 0x5f, 0x87}, |  | ||||||
|     {0x87, 0x5f, 0xaf}, |  | ||||||
|     {0x87, 0x5f, 0xd7}, |  | ||||||
|     {0x87, 0x5f, 0xff}, |  | ||||||
|     {0x87, 0x87, 0x00}, |  | ||||||
|     {0x87, 0x87, 0x5f}, |  | ||||||
|     {0x87, 0x87, 0x87}, |  | ||||||
|     {0x87, 0x87, 0xaf}, |  | ||||||
|     {0x87, 0x87, 0xd7}, |  | ||||||
|     {0x87, 0x87, 0xff}, |  | ||||||
|     {0x87, 0xaf, 0x00}, |  | ||||||
|     {0x87, 0xaf, 0x5f}, |  | ||||||
|     {0x87, 0xaf, 0x87}, |  | ||||||
|     {0x87, 0xaf, 0xaf}, |  | ||||||
|     {0x87, 0xaf, 0xd7}, |  | ||||||
|     {0x87, 0xaf, 0xff}, |  | ||||||
|     {0x87, 0xd7, 0x00}, |  | ||||||
|     {0x87, 0xd7, 0x5f}, |  | ||||||
|     {0x87, 0xd7, 0x87}, |  | ||||||
|     {0x87, 0xd7, 0xaf}, |  | ||||||
|     {0x87, 0xd7, 0xd7}, |  | ||||||
|     {0x87, 0xd7, 0xff}, |  | ||||||
|     {0x87, 0xff, 0x00}, |  | ||||||
|     {0x87, 0xff, 0x5f}, |  | ||||||
|     {0x87, 0xff, 0x87}, |  | ||||||
|     {0x87, 0xff, 0xaf}, |  | ||||||
|     {0x87, 0xff, 0xd7}, |  | ||||||
|     {0x87, 0xff, 0xff}, |  | ||||||
|     {0xaf, 0x00, 0x00}, |  | ||||||
|     {0xaf, 0x00, 0x5f}, |  | ||||||
|     {0xaf, 0x00, 0x87}, |  | ||||||
|     {0xaf, 0x00, 0xaf}, |  | ||||||
|     {0xaf, 0x00, 0xd7}, |  | ||||||
|     {0xaf, 0x00, 0xff}, |  | ||||||
|     {0xaf, 0x5f, 0x00}, |  | ||||||
|     {0xaf, 0x5f, 0x5f}, |  | ||||||
|     {0xaf, 0x5f, 0x87}, |  | ||||||
|     {0xaf, 0x5f, 0xaf}, |  | ||||||
|     {0xaf, 0x5f, 0xd7}, |  | ||||||
|     {0xaf, 0x5f, 0xff}, |  | ||||||
|     {0xaf, 0x87, 0x00}, |  | ||||||
|     {0xaf, 0x87, 0x5f}, |  | ||||||
|     {0xaf, 0x87, 0x87}, |  | ||||||
|     {0xaf, 0x87, 0xaf}, |  | ||||||
|     {0xaf, 0x87, 0xd7}, |  | ||||||
|     {0xaf, 0x87, 0xff}, |  | ||||||
|     {0xaf, 0xaf, 0x00}, |  | ||||||
|     {0xaf, 0xaf, 0x5f}, |  | ||||||
|     {0xaf, 0xaf, 0x87}, |  | ||||||
|     {0xaf, 0xaf, 0xaf}, |  | ||||||
|     {0xaf, 0xaf, 0xd7}, |  | ||||||
|     {0xaf, 0xaf, 0xff}, |  | ||||||
|     {0xaf, 0xd7, 0x00}, |  | ||||||
|     {0xaf, 0xd7, 0x5f}, |  | ||||||
|     {0xaf, 0xd7, 0x87}, |  | ||||||
|     {0xaf, 0xd7, 0xaf}, |  | ||||||
|     {0xaf, 0xd7, 0xd7}, |  | ||||||
|     {0xaf, 0xd7, 0xff}, |  | ||||||
|     {0xaf, 0xff, 0x00}, |  | ||||||
|     {0xaf, 0xff, 0x5f}, |  | ||||||
|     {0xaf, 0xff, 0x87}, |  | ||||||
|     {0xaf, 0xff, 0xaf}, |  | ||||||
|     {0xaf, 0xff, 0xd7}, |  | ||||||
|     {0xaf, 0xff, 0xff}, |  | ||||||
|     {0xd7, 0x00, 0x00}, |  | ||||||
|     {0xd7, 0x00, 0x5f}, |  | ||||||
|     {0xd7, 0x00, 0x87}, |  | ||||||
|     {0xd7, 0x00, 0xaf}, |  | ||||||
|     {0xd7, 0x00, 0xd7}, |  | ||||||
|     {0xd7, 0x00, 0xff}, |  | ||||||
|     {0xd7, 0x5f, 0x00}, |  | ||||||
|     {0xd7, 0x5f, 0x5f}, |  | ||||||
|     {0xd7, 0x5f, 0x87}, |  | ||||||
|     {0xd7, 0x5f, 0xaf}, |  | ||||||
|     {0xd7, 0x5f, 0xd7}, |  | ||||||
|     {0xd7, 0x5f, 0xff}, |  | ||||||
|     {0xd7, 0x87, 0x00}, |  | ||||||
|     {0xd7, 0x87, 0x5f}, |  | ||||||
|     {0xd7, 0x87, 0x87}, |  | ||||||
|     {0xd7, 0x87, 0xaf}, |  | ||||||
|     {0xd7, 0x87, 0xd7}, |  | ||||||
|     {0xd7, 0x87, 0xff}, |  | ||||||
|     {0xd7, 0xaf, 0x00}, |  | ||||||
|     {0xd7, 0xaf, 0x5f}, |  | ||||||
|     {0xd7, 0xaf, 0x87}, |  | ||||||
|     {0xd7, 0xaf, 0xaf}, |  | ||||||
|     {0xd7, 0xaf, 0xd7}, |  | ||||||
|     {0xd7, 0xaf, 0xff}, |  | ||||||
|     {0xd7, 0xd7, 0x00}, |  | ||||||
|     {0xd7, 0xd7, 0x5f}, |  | ||||||
|     {0xd7, 0xd7, 0x87}, |  | ||||||
|     {0xd7, 0xd7, 0xaf}, |  | ||||||
|     {0xd7, 0xd7, 0xd7}, |  | ||||||
|     {0xd7, 0xd7, 0xff}, |  | ||||||
|     {0xd7, 0xff, 0x00}, |  | ||||||
|     {0xd7, 0xff, 0x5f}, |  | ||||||
|     {0xd7, 0xff, 0x87}, |  | ||||||
|     {0xd7, 0xff, 0xaf}, |  | ||||||
|     {0xd7, 0xff, 0xd7}, |  | ||||||
|     {0xd7, 0xff, 0xff}, |  | ||||||
|     {0xff, 0x00, 0x00}, |  | ||||||
|     {0xff, 0x00, 0x5f}, |  | ||||||
|     {0xff, 0x00, 0x87}, |  | ||||||
|     {0xff, 0x00, 0xaf}, |  | ||||||
|     {0xff, 0x00, 0xd7}, |  | ||||||
|     {0xff, 0x00, 0xff}, |  | ||||||
|     {0xff, 0x5f, 0x00}, |  | ||||||
|     {0xff, 0x5f, 0x5f}, |  | ||||||
|     {0xff, 0x5f, 0x87}, |  | ||||||
|     {0xff, 0x5f, 0xaf}, |  | ||||||
|     {0xff, 0x5f, 0xd7}, |  | ||||||
|     {0xff, 0x5f, 0xff}, |  | ||||||
|     {0xff, 0x87, 0x00}, |  | ||||||
|     {0xff, 0x87, 0x5f}, |  | ||||||
|     {0xff, 0x87, 0x87}, |  | ||||||
|     {0xff, 0x87, 0xaf}, |  | ||||||
|     {0xff, 0x87, 0xd7}, |  | ||||||
|     {0xff, 0x87, 0xff}, |  | ||||||
|     {0xff, 0xaf, 0x00}, |  | ||||||
|     {0xff, 0xaf, 0x5f}, |  | ||||||
|     {0xff, 0xaf, 0x87}, |  | ||||||
|     {0xff, 0xaf, 0xaf}, |  | ||||||
|     {0xff, 0xaf, 0xd7}, |  | ||||||
|     {0xff, 0xaf, 0xff}, |  | ||||||
|     {0xff, 0xd7, 0x00}, |  | ||||||
|     {0xff, 0xd7, 0x5f}, |  | ||||||
|     {0xff, 0xd7, 0x87}, |  | ||||||
|     {0xff, 0xd7, 0xaf}, |  | ||||||
|     {0xff, 0xd7, 0xd7}, |  | ||||||
|     {0xff, 0xd7, 0xff}, |  | ||||||
|     {0xff, 0xff, 0x00}, |  | ||||||
|     {0xff, 0xff, 0x5f}, |  | ||||||
|     {0xff, 0xff, 0x87}, |  | ||||||
|     {0xff, 0xff, 0xaf}, |  | ||||||
|     {0xff, 0xff, 0xd7}, |  | ||||||
|     {0xff, 0xff, 0xff}, |  | ||||||
| 
 |  | ||||||
|     /* 232..255: xterm256 grayscale */ |  | ||||||
|     {0x08, 0x08, 0x08}, /*  8 */ |  | ||||||
|     {0x12, 0x12, 0x12}, /* 10 */ |  | ||||||
|     {0x1c, 0x1c, 0x1c}, /* 10 */ |  | ||||||
|     {0x26, 0x26, 0x26}, /* 10 */ |  | ||||||
|     {0x30, 0x30, 0x30}, /* .. */ |  | ||||||
|     {0x3a, 0x3a, 0x3a}, |  | ||||||
|     {0x44, 0x44, 0x44}, |  | ||||||
|     {0x4e, 0x4e, 0x4e}, |  | ||||||
|     {0x58, 0x58, 0x58}, |  | ||||||
|     {0x62, 0x62, 0x62}, |  | ||||||
|     {0x6c, 0x6c, 0x6c}, |  | ||||||
|     {0x76, 0x76, 0x76}, |  | ||||||
|     {0x80, 0x80, 0x80}, |  | ||||||
|     {0x8a, 0x8a, 0x8a}, |  | ||||||
|     {0x94, 0x94, 0x94}, |  | ||||||
|     {0x9e, 0x9e, 0x9e}, |  | ||||||
|     {0xa8, 0xa8, 0xa8}, |  | ||||||
|     {0xb2, 0xb2, 0xb2}, |  | ||||||
|     {0xbc, 0xbc, 0xbc}, |  | ||||||
|     {0xc6, 0xc6, 0xc6}, |  | ||||||
|     {0xd0, 0xd0, 0xd0}, |  | ||||||
|     {0xda, 0xda, 0xda}, |  | ||||||
|     {0xe4, 0xe4, 0xe4}, |  | ||||||
|     {0xee, 0xee, 0xee}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const struct Rgb kXtermRgbAppleFg[] = { |  | ||||||
|     {0, 0, 0},       {192, 55, 41},   {48, 187, 49},   {173, 172, 53}, |  | ||||||
|     {73, 76, 224},   {209, 65, 209},  {60, 187, 199},  {203, 204, 205}, |  | ||||||
|     {154, 155, 156}, {249, 59, 44},   {62, 229, 55},   {234, 234, 62}, |  | ||||||
|     {89, 63, 251},   {247, 67, 245},  {48, 239, 239},  {233, 235, 235}, |  | ||||||
|     {47, 49, 49},    {60, 46, 142},   {67, 51, 180},   {74, 56, 218}, |  | ||||||
|     {82, 62, 248},   {89, 63, 251},   {46, 127, 43},   {46, 127, 127}, |  | ||||||
|     {49, 127, 167},  {60, 127, 207},  {63, 127, 241},  {70, 126, 251}, |  | ||||||
|     {57, 161, 50},   {47, 161, 122},  {50, 161, 161},  {60, 161, 200}, |  | ||||||
|     {53, 161, 237},  {65, 160, 252},  {45, 194, 51},   {58, 194, 118}, |  | ||||||
|     {51, 194, 156},  {59, 194, 194},  {48, 194, 233},  {63, 194, 252}, |  | ||||||
|     {62, 227, 55},   {55, 227, 115},  {48, 227, 151},  {63, 227, 189}, |  | ||||||
|     {52, 227, 227},  {66, 227, 253},  {51, 252, 57},   {53, 252, 111}, |  | ||||||
|     {63, 252, 147},  {58, 252, 184},  {59, 252, 222},  {62, 253, 251}, |  | ||||||
|     {138, 49, 43},   {134, 55, 134},  {134, 58, 174},  {133, 61, 213}, |  | ||||||
|     {134, 67, 244},  {134, 65, 251},  {125, 124, 46},  {124, 125, 125}, |  | ||||||
|     {122, 125, 165}, {123, 126, 205}, {124, 126, 243}, {125, 125, 251}, |  | ||||||
|     {120, 159, 47},  {118, 159, 121}, {118, 159, 160}, {117, 160, 199}, |  | ||||||
|     {118, 160, 238}, {119, 160, 252}, {115, 193, 53},  {113, 193, 117}, |  | ||||||
|     {114, 193, 155}, {111, 193, 193}, {113, 194, 232}, {112, 193, 252}, |  | ||||||
|     {110, 226, 53},  {108, 226, 114}, {110, 226, 151}, {106, 226, 189}, |  | ||||||
|     {105, 227, 227}, {105, 226, 252}, {99, 251, 59},   {103, 251, 111}, |  | ||||||
|     {104, 251, 146}, {97, 252, 184},  {102, 252, 221}, {98, 254, 250}, |  | ||||||
|     {175, 54, 40},   {172, 58, 130},  {170, 61, 170},  {170, 66, 210}, |  | ||||||
|     {169, 67, 245},  {168, 69, 251},  {164, 123, 47},  {162, 123, 124}, |  | ||||||
|     {161, 124, 163}, {161, 124, 203}, {160, 125, 238}, {160, 125, 251}, |  | ||||||
|     {158, 157, 47},  {157, 158, 120}, {157, 158, 159}, {155, 158, 198}, |  | ||||||
|     {155, 159, 236}, {155, 158, 252}, {153, 192, 55},  {152, 192, 117}, |  | ||||||
|     {151, 192, 154}, {151, 192, 193}, {150, 192, 231}, {150, 192, 251}, |  | ||||||
|     {148, 225, 53},  {147, 225, 114}, {146, 225, 150}, {147, 226, 188}, |  | ||||||
|     {145, 226, 226}, {145, 226, 250}, {142, 251, 61},  {141, 251, 111}, |  | ||||||
|     {141, 252, 146}, {142, 253, 183}, {139, 254, 221}, {138, 255, 249}, |  | ||||||
|     {211, 59, 40},   {209, 63, 126},  {207, 63, 166},  {206, 64, 206}, |  | ||||||
|     {205, 69, 243},  {204, 72, 252},  {202, 121, 45},  {201, 122, 122}, |  | ||||||
|     {200, 122, 161}, {199, 123, 200}, {199, 124, 238}, {197, 124, 252}, |  | ||||||
|     {197, 156, 51},  {195, 156, 119}, {195, 157, 157}, {194, 157, 196}, |  | ||||||
|     {193, 157, 234}, {193, 157, 252}, {191, 190, 54},  {190, 190, 116}, |  | ||||||
|     {189, 191, 153}, {190, 191, 191}, {188, 191, 229}, {187, 191, 251}, |  | ||||||
|     {186, 224, 55},  {185, 224, 113}, {184, 224, 150}, {184, 224, 187}, |  | ||||||
|     {184, 225, 225}, {182, 224, 251}, {180, 253, 62},  {180, 253, 111}, |  | ||||||
|     {179, 253, 146}, {179, 253, 183}, {179, 254, 220}, {177, 252, 249}, |  | ||||||
|     {244, 59, 43},   {243, 62, 123},  {241, 65, 162},  {241, 69, 202}, |  | ||||||
|     {240, 70, 238},  {238, 69, 252},  {239, 119, 50},  {238, 120, 120}, |  | ||||||
|     {236, 121, 159}, {235, 121, 198}, {235, 123, 236}, {234, 123, 252}, |  | ||||||
|     {234, 154, 53},  {233, 154, 118}, {232, 155, 156}, {231, 155, 194}, |  | ||||||
|     {231, 156, 233}, {230, 156, 252}, {229, 188, 53},  {228, 189, 115}, |  | ||||||
|     {227, 189, 152}, {227, 189, 190}, {226, 189, 228}, {225, 189, 253}, |  | ||||||
|     {223, 222, 60},  {223, 223, 113}, {222, 223, 149}, {222, 223, 186}, |  | ||||||
|     {222, 223, 224}, {220, 223, 252}, {218, 251, 61},  {217, 251, 109}, |  | ||||||
|     {217, 251, 145}, {217, 251, 182}, {216, 251, 219}, {216, 251, 250}, |  | ||||||
|     {252, 63, 43},   {252, 64, 120},  {252, 64, 159},  {252, 65, 198}, |  | ||||||
|     {252, 67, 236},  {252, 72, 252},  {253, 117, 47},  {253, 118, 118}, |  | ||||||
|     {253, 119, 156}, {253, 120, 194}, {253, 120, 233}, {252, 121, 252}, |  | ||||||
|     {253, 152, 49},  {252, 152, 116}, {252, 153, 153}, {253, 153, 192}, |  | ||||||
|     {252, 154, 229}, {251, 154, 251}, {253, 186, 56},  {251, 187, 114}, |  | ||||||
|     {251, 187, 151}, {252, 187, 188}, {252, 188, 226}, {251, 188, 251}, |  | ||||||
|     {251, 221, 61},  {250, 221, 112}, {250, 221, 148}, {250, 221, 185}, |  | ||||||
|     {251, 222, 222}, {251, 222, 251}, {251, 250, 58},  {250, 250, 109}, |  | ||||||
|     {249, 250, 144}, {247, 251, 181}, {247, 253, 218}, {254, 255, 255}, |  | ||||||
|     {52, 53, 53},    {57, 58, 59},    {66, 67, 67},    {75, 76, 76}, |  | ||||||
|     {84, 85, 85},    {92, 93, 94},    {101, 102, 102}, {109, 111, 111}, |  | ||||||
|     {118, 119, 119}, {126, 127, 128}, {134, 136, 136}, {143, 144, 145}, |  | ||||||
|     {151, 152, 153}, {159, 161, 161}, {167, 169, 169}, {176, 177, 177}, |  | ||||||
|     {184, 185, 186}, {192, 193, 194}, {200, 201, 202}, {208, 209, 210}, |  | ||||||
|     {216, 218, 218}, {224, 226, 226}, {232, 234, 234}, {240, 242, 242}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const struct Rgb kXtermRgbAppleBg[] = { |  | ||||||
|     {0, 0, 0},       {151, 4, 12},    {23, 164, 26},   {153, 152, 29}, |  | ||||||
|     {8, 43, 181},    {177, 25, 176},  {26, 166, 177},  {191, 191, 191}, |  | ||||||
|     {132, 132, 132}, {227, 10, 23},   {33, 215, 38},   {229, 228, 49}, |  | ||||||
|     {11, 36, 251},   {227, 35, 227},  {39, 229, 228},  {230, 229, 230}, |  | ||||||
|     {0, 0, 0},       {1, 7, 93},      {3, 14, 133},    {5, 21, 172}, |  | ||||||
|     {7, 28, 211},    {11, 36, 251},   {8, 94, 11},     {10, 95, 95}, |  | ||||||
|     {11, 96, 133},   {13, 97, 173},   {15, 99, 212},   {18, 101, 251}, |  | ||||||
|     {17, 134, 20},   {18, 134, 96},   {18, 135, 134},  {20, 136, 173}, |  | ||||||
|     {21, 137, 212},  {23, 138, 251},  {25, 173, 29},   {26, 174, 98}, |  | ||||||
|     {26, 174, 136},  {27, 175, 174},  {28, 175, 213},  {30, 176, 252}, |  | ||||||
|     {33, 213, 38},   {34, 213, 101},  {34, 214, 137},  {35, 214, 175}, |  | ||||||
|     {36, 215, 214},  {37, 215, 253},  {41, 253, 47},   {42, 253, 104}, |  | ||||||
|     {42, 253, 140},  {43, 253, 177},  {44, 254, 215},  {45, 255, 254}, |  | ||||||
|     {94, 2, 4},      {94, 8, 94},     {94, 15, 133},   {94, 22, 172}, |  | ||||||
|     {95, 29, 211},   {95, 36, 251},   {95, 94, 14},    {95, 95, 95}, |  | ||||||
|     {95, 96, 134},   {95, 97, 173},   {96, 99, 212},   {96, 101, 251}, |  | ||||||
|     {96, 134, 22},   {96, 134, 96},   {96, 135, 135},  {97, 136, 173}, |  | ||||||
|     {97, 137, 212},  {97, 138, 252},  {98, 173, 30},   {98, 174, 98}, |  | ||||||
|     {98, 174, 136},  {98, 175, 174},  {98, 176, 213},  {99, 177, 252}, |  | ||||||
|     {100, 213, 39},  {100, 213, 101}, {100, 214, 138}, {100, 214, 176}, |  | ||||||
|     {101, 215, 214}, {101, 215, 253}, {102, 253, 48},  {103, 253, 104}, |  | ||||||
|     {103, 253, 140}, {103, 253, 177}, {103, 254, 215}, {104, 255, 254}, |  | ||||||
|     {133, 3, 9},     {133, 10, 94},   {134, 16, 133},  {134, 23, 172}, |  | ||||||
|     {134, 30, 212},  {134, 37, 251},  {134, 94, 18},   {134, 95, 96}, |  | ||||||
|     {134, 96, 134},  {134, 97, 173},  {135, 99, 212},  {135, 101, 251}, |  | ||||||
|     {135, 134, 25},  {135, 134, 97},  {135, 135, 135}, {135, 136, 174}, |  | ||||||
|     {135, 137, 213}, {136, 138, 252}, {136, 173, 32},  {136, 174, 99}, |  | ||||||
|     {136, 174, 136}, {136, 175, 175}, {136, 176, 213}, {137, 177, 252}, |  | ||||||
|     {137, 213, 40},  {137, 213, 102}, {138, 214, 138}, {138, 214, 176}, |  | ||||||
|     {138, 215, 214}, {138, 216, 253}, {139, 253, 49},  {139, 253, 105}, |  | ||||||
|     {139, 253, 140}, {139, 254, 178}, {140, 254, 216}, {140, 255, 254}, |  | ||||||
|     {173, 6, 15},    {173, 12, 95},   {173, 18, 134},  {173, 24, 173}, |  | ||||||
|     {173, 31, 212},  {174, 38, 251},  {173, 95, 22},   {174, 95, 96}, |  | ||||||
|     {174, 96, 135},  {174, 98, 173},  {174, 99, 212},  {174, 101, 252}, |  | ||||||
|     {174, 134, 28},  {174, 135, 98},  {174, 135, 136}, {174, 136, 174}, |  | ||||||
|     {174, 137, 213}, {175, 139, 252}, {175, 174, 35},  {175, 174, 100}, |  | ||||||
|     {175, 174, 137}, {175, 175, 175}, {175, 176, 214}, {175, 177, 253}, |  | ||||||
|     {176, 213, 43},  {176, 213, 102}, {176, 214, 139}, {176, 214, 176}, |  | ||||||
|     {176, 215, 215}, {176, 216, 253}, {177, 253, 51},  {177, 253, 105}, |  | ||||||
|     {177, 253, 141}, {177, 254, 178}, {178, 254, 216}, {178, 255, 254}, |  | ||||||
|     {213, 9, 21},    {213, 15, 96},   {213, 20, 135},  {241, 69, 202}, |  | ||||||
|     {213, 32, 212},  {213, 39, 251},  {213, 95, 27},   {213, 96, 97}, |  | ||||||
|     {213, 97, 135},  {213, 98, 174},  {213, 100, 213}, {213, 102, 252}, |  | ||||||
|     {213, 134, 32},  {213, 135, 99},  {213, 135, 136}, {214, 136, 175}, |  | ||||||
|     {214, 137, 213}, {214, 139, 252}, {214, 174, 38},  {214, 174, 101}, |  | ||||||
|     {214, 175, 138}, {214, 175, 176}, {214, 176, 214}, {214, 177, 253}, |  | ||||||
|     {215, 213, 45},  {215, 214, 103}, {215, 214, 139}, {215, 214, 177}, |  | ||||||
|     {215, 215, 215}, {215, 216, 254}, {216, 253, 53},  {216, 253, 106}, |  | ||||||
|     {216, 253, 141}, {216, 254, 178}, {216, 254, 216}, {216, 255, 255}, |  | ||||||
|     {252, 13, 27},   {252, 18, 98},   {252, 22, 135},  {252, 28, 174}, |  | ||||||
|     {252, 34, 213},  {252, 40, 252},  {252, 96, 32},   {252, 96, 99}, |  | ||||||
|     {252, 97, 136},  {253, 99, 175},  {253, 100, 213}, {253, 102, 252}, |  | ||||||
|     {253, 135, 36},  {253, 135, 100}, {253, 136, 137}, {253, 137, 175}, |  | ||||||
|     {253, 138, 214}, {253, 139, 253}, {253, 174, 42},  {253, 174, 102}, |  | ||||||
|     {253, 175, 138}, {253, 175, 176}, {253, 176, 215}, {254, 177, 253}, |  | ||||||
|     {254, 213, 48},  {254, 214, 105}, {254, 214, 140}, {254, 215, 177}, |  | ||||||
|     {254, 215, 216}, {254, 216, 254}, {255, 253, 56},  {255, 253, 108}, |  | ||||||
|     {255, 253, 142}, {255, 254, 179}, {255, 254, 217}, {255, 255, 255}, |  | ||||||
|     {8, 8, 8},       {18, 18, 18},    {28, 28, 28},    {38, 38, 38}, |  | ||||||
|     {48, 48, 48},    {58, 58, 58},    {68, 68, 68},    {78, 78, 78}, |  | ||||||
|     {88, 88, 88},    {98, 98, 98},    {108, 108, 108}, {118, 118, 118}, |  | ||||||
|     {128, 128, 128}, {138, 138, 138}, {148, 148, 148}, {158, 158, 158}, |  | ||||||
|     {168, 168, 168}, {178, 178, 178}, {188, 188, 188}, {198, 198, 198}, |  | ||||||
|     {208, 208, 208}, {218, 218, 218}, {228, 228, 228}, {238, 238, 238}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const struct XtermDb { |  | ||||||
|   struct Rgb rgb; |  | ||||||
|   const char *text; |  | ||||||
| } kXtermDb[] = { |  | ||||||
|     {{0x00, 0x00, 0x00}, "0      Black             #000000"}, |  | ||||||
|     {{0x80, 0x00, 0x00}, "1      Maroon            #800000"}, |  | ||||||
|     {{0x00, 0x80, 0x00}, "2      Green             #008000"}, |  | ||||||
|     {{0x80, 0x80, 0x00}, "3      Olive             #808000"}, |  | ||||||
|     {{0x00, 0x00, 0x80}, "4      Navy              #000080"}, |  | ||||||
|     {{0x80, 0x00, 0x80}, "5      Purple            #800080"}, |  | ||||||
|     {{0x00, 0x80, 0x80}, "6      Teal              #008080"}, |  | ||||||
|     {{0xc0, 0xc0, 0xc0}, "7      Silver            #c0c0c0"}, |  | ||||||
|     {{0x80, 0x80, 0x80}, "8      Grey              #808080"}, |  | ||||||
|     {{0xff, 0x00, 0x00}, "9      Red               #ff0000"}, |  | ||||||
|     {{0x00, 0xff, 0x00}, "10     Lime              #00ff00"}, |  | ||||||
|     {{0xff, 0xff, 0x00}, "11     Yellow            #ffff00"}, |  | ||||||
|     {{0x00, 0x00, 0xff}, "12     Blue              #0000ff"}, |  | ||||||
|     {{0xff, 0x00, 0xff}, "13     Fuchsia           #ff00ff"}, |  | ||||||
|     {{0x00, 0xff, 0xff}, "14     Aqua              #00ffff"}, |  | ||||||
|     {{0xff, 0xff, 0xff}, "15     White             #ffffff"}, |  | ||||||
|     {{0x00, 0x00, 0x00}, "16     Grey0             #000000"}, |  | ||||||
|     {{0x00, 0x00, 0x5f}, "17     NavyBlue          #00005f"}, |  | ||||||
|     {{0x00, 0x00, 0x87}, "18     DarkBlue          #000087"}, |  | ||||||
|     {{0x00, 0x00, 0xaf}, "19     Blue3             #0000af"}, |  | ||||||
|     {{0x00, 0x00, 0xd7}, "20     Blue3             #0000d7"}, |  | ||||||
|     {{0x00, 0x00, 0xff}, "21     Blue1             #0000ff"}, |  | ||||||
|     {{0x00, 0x5f, 0x00}, "22     DarkGreen         #005f00"}, |  | ||||||
|     {{0x00, 0x5f, 0x5f}, "23     DeepSkyBlue4      #005f5f"}, |  | ||||||
|     {{0x00, 0x5f, 0x87}, "24     DeepSkyBlue4      #005f87"}, |  | ||||||
|     {{0x00, 0x5f, 0xaf}, "25     DeepSkyBlue4      #005faf"}, |  | ||||||
|     {{0x00, 0x5f, 0xd7}, "26     DodgerBlue3       #005fd7"}, |  | ||||||
|     {{0x00, 0x5f, 0xff}, "27     DodgerBlue2       #005fff"}, |  | ||||||
|     {{0x00, 0x87, 0x00}, "28     Green4            #008700"}, |  | ||||||
|     {{0x00, 0x87, 0x5f}, "29     SpringGreen4      #00875f"}, |  | ||||||
|     {{0x00, 0x87, 0x87}, "30     Turquoise4        #008787"}, |  | ||||||
|     {{0x00, 0x87, 0xaf}, "31     DeepSkyBlue3      #0087af"}, |  | ||||||
|     {{0x00, 0x87, 0xd7}, "32     DeepSkyBlue3      #0087d7"}, |  | ||||||
|     {{0x00, 0x87, 0xff}, "33     DodgerBlue1       #0087ff"}, |  | ||||||
|     {{0x00, 0xaf, 0x00}, "34     Green3            #00af00"}, |  | ||||||
|     {{0x00, 0xaf, 0x5f}, "35     SpringGreen3      #00af5f"}, |  | ||||||
|     {{0x00, 0xaf, 0x87}, "36     DarkCyan          #00af87"}, |  | ||||||
|     {{0x00, 0xaf, 0xaf}, "37     LightSeaGreen     #00afaf"}, |  | ||||||
|     {{0x00, 0xaf, 0xd7}, "38     DeepSkyBlue2      #00afd7"}, |  | ||||||
|     {{0x00, 0xaf, 0xff}, "39     DeepSkyBlue1      #00afff"}, |  | ||||||
|     {{0x00, 0xd7, 0x00}, "40     Green3            #00d700"}, |  | ||||||
|     {{0x00, 0xd7, 0x5f}, "41     SpringGreen3      #00d75f"}, |  | ||||||
|     {{0x00, 0xd7, 0x87}, "42     SpringGreen2      #00d787"}, |  | ||||||
|     {{0x00, 0xd7, 0xaf}, "43     Cyan3             #00d7af"}, |  | ||||||
|     {{0x00, 0xd7, 0xd7}, "44     DarkTurquoise     #00d7d7"}, |  | ||||||
|     {{0x00, 0xd7, 0xff}, "45     Turquoise2        #00d7ff"}, |  | ||||||
|     {{0x00, 0xff, 0x00}, "46     Green1            #00ff00"}, |  | ||||||
|     {{0x00, 0xff, 0x5f}, "47     SpringGreen2      #00ff5f"}, |  | ||||||
|     {{0x00, 0xff, 0x87}, "48     SpringGreen1      #00ff87"}, |  | ||||||
|     {{0x00, 0xff, 0xaf}, "49     MediumSpringGreen #00ffaf"}, |  | ||||||
|     {{0x00, 0xff, 0xd7}, "50     Cyan2             #00ffd7"}, |  | ||||||
|     {{0x00, 0xff, 0xff}, "51     Cyan1             #00ffff"}, |  | ||||||
|     {{0x5f, 0x00, 0x00}, "52     DarkRed           #5f0000"}, |  | ||||||
|     {{0x5f, 0x00, 0x5f}, "53     DeepPink4         #5f005f"}, |  | ||||||
|     {{0x5f, 0x00, 0x87}, "54     Purple4           #5f0087"}, |  | ||||||
|     {{0x5f, 0x00, 0xaf}, "55     Purple4           #5f00af"}, |  | ||||||
|     {{0x5f, 0x00, 0xd7}, "56     Purple3           #5f00d7"}, |  | ||||||
|     {{0x5f, 0x00, 0xff}, "57     BlueViolet        #5f00ff"}, |  | ||||||
|     {{0x5f, 0x5f, 0x00}, "58     Orange4           #5f5f00"}, |  | ||||||
|     {{0x5f, 0x5f, 0x5f}, "59     Grey37            #5f5f5f"}, |  | ||||||
|     {{0x5f, 0x5f, 0x87}, "60     MediumPurple4     #5f5f87"}, |  | ||||||
|     {{0x5f, 0x5f, 0xaf}, "61     SlateBlue3        #5f5faf"}, |  | ||||||
|     {{0x5f, 0x5f, 0xd7}, "62     SlateBlue3        #5f5fd7"}, |  | ||||||
|     {{0x5f, 0x5f, 0xff}, "63     RoyalBlue1        #5f5fff"}, |  | ||||||
|     {{0x5f, 0x87, 0x00}, "64     Chartreuse4       #5f8700"}, |  | ||||||
|     {{0x5f, 0x87, 0x5f}, "65     DarkSeaGreen4     #5f875f"}, |  | ||||||
|     {{0x5f, 0x87, 0x87}, "66     PaleTurquoise4    #5f8787"}, |  | ||||||
|     {{0x5f, 0x87, 0xaf}, "67     SteelBlue         #5f87af"}, |  | ||||||
|     {{0x5f, 0x87, 0xd7}, "68     SteelBlue3        #5f87d7"}, |  | ||||||
|     {{0x5f, 0x87, 0xff}, "69     CornflowerBlue    #5f87ff"}, |  | ||||||
|     {{0x5f, 0xaf, 0x00}, "70     Chartreuse3       #5faf00"}, |  | ||||||
|     {{0x5f, 0xaf, 0x5f}, "71     DarkSeaGreen4     #5faf5f"}, |  | ||||||
|     {{0x5f, 0xaf, 0x87}, "72     CadetBlue         #5faf87"}, |  | ||||||
|     {{0x5f, 0xaf, 0xaf}, "73     CadetBlue         #5fafaf"}, |  | ||||||
|     {{0x5f, 0xaf, 0xd7}, "74     SkyBlue3          #5fafd7"}, |  | ||||||
|     {{0x5f, 0xaf, 0xff}, "75     SteelBlue1        #5fafff"}, |  | ||||||
|     {{0x5f, 0xd7, 0x00}, "76     Chartreuse3       #5fd700"}, |  | ||||||
|     {{0x5f, 0xd7, 0x5f}, "77     PaleGreen3        #5fd75f"}, |  | ||||||
|     {{0x5f, 0xd7, 0x87}, "78     SeaGreen3         #5fd787"}, |  | ||||||
|     {{0x5f, 0xd7, 0xaf}, "79     Aquamarine3       #5fd7af"}, |  | ||||||
|     {{0x5f, 0xd7, 0xd7}, "80     MediumTurquoise   #5fd7d7"}, |  | ||||||
|     {{0x5f, 0xd7, 0xff}, "81     SteelBlue1        #5fd7ff"}, |  | ||||||
|     {{0x5f, 0xff, 0x00}, "82     Chartreuse2       #5fff00"}, |  | ||||||
|     {{0x5f, 0xff, 0x5f}, "83     SeaGreen2         #5fff5f"}, |  | ||||||
|     {{0x5f, 0xff, 0x87}, "84     SeaGreen1         #5fff87"}, |  | ||||||
|     {{0x5f, 0xff, 0xaf}, "85     SeaGreen1         #5fffaf"}, |  | ||||||
|     {{0x5f, 0xff, 0xd7}, "86     Aquamarine1       #5fffd7"}, |  | ||||||
|     {{0x5f, 0xff, 0xff}, "87     DarkSlateGray2    #5fffff"}, |  | ||||||
|     {{0x87, 0x00, 0x00}, "88     DarkRed           #870000"}, |  | ||||||
|     {{0x87, 0x00, 0x5f}, "89     DeepPink4         #87005f"}, |  | ||||||
|     {{0x87, 0x00, 0x87}, "90     DarkMagenta       #870087"}, |  | ||||||
|     {{0x87, 0x00, 0xaf}, "91     DarkMagenta       #8700af"}, |  | ||||||
|     {{0x87, 0x00, 0xd7}, "92     DarkViolet        #8700d7"}, |  | ||||||
|     {{0x87, 0x00, 0xff}, "93     Purple            #8700ff"}, |  | ||||||
|     {{0x87, 0x5f, 0x00}, "94     Orange4           #875f00"}, |  | ||||||
|     {{0x87, 0x5f, 0x5f}, "95     LightPink4        #875f5f"}, |  | ||||||
|     {{0x87, 0x5f, 0x87}, "96     Plum4             #875f87"}, |  | ||||||
|     {{0x87, 0x5f, 0xaf}, "97     MediumPurple3     #875faf"}, |  | ||||||
|     {{0x87, 0x5f, 0xd7}, "98     MediumPurple3     #875fd7"}, |  | ||||||
|     {{0x87, 0x5f, 0xff}, "99     SlateBlue1        #875fff"}, |  | ||||||
|     {{0x87, 0x87, 0x00}, "100    Yellow4           #878700"}, |  | ||||||
|     {{0x87, 0x87, 0x5f}, "101    Wheat4            #87875f"}, |  | ||||||
|     {{0x87, 0x87, 0x87}, "102    Grey53            #878787"}, |  | ||||||
|     {{0x87, 0x87, 0xaf}, "103    LightSlateGrey    #8787af"}, |  | ||||||
|     {{0x87, 0x87, 0xd7}, "104    MediumPurple      #8787d7"}, |  | ||||||
|     {{0x87, 0x87, 0xff}, "105    LightSlateBlue    #8787ff"}, |  | ||||||
|     {{0x87, 0xaf, 0x00}, "106    Yellow4           #87af00"}, |  | ||||||
|     {{0x87, 0xaf, 0x5f}, "107    DarkOliveGreen3   #87af5f"}, |  | ||||||
|     {{0x87, 0xaf, 0x87}, "108    DarkSeaGreen      #87af87"}, |  | ||||||
|     {{0x87, 0xaf, 0xaf}, "109    LightSkyBlue3     #87afaf"}, |  | ||||||
|     {{0x87, 0xaf, 0xd7}, "110    LightSkyBlue3     #87afd7"}, |  | ||||||
|     {{0x87, 0xaf, 0xff}, "111    SkyBlue2          #87afff"}, |  | ||||||
|     {{0x87, 0xd7, 0x00}, "112    Chartreuse2       #87d700"}, |  | ||||||
|     {{0x87, 0xd7, 0x5f}, "113    DarkOliveGreen3   #87d75f"}, |  | ||||||
|     {{0x87, 0xd7, 0x87}, "114    PaleGreen3        #87d787"}, |  | ||||||
|     {{0x87, 0xd7, 0xaf}, "115    DarkSeaGreen3     #87d7af"}, |  | ||||||
|     {{0x87, 0xd7, 0xd7}, "116    DarkSlateGray3    #87d7d7"}, |  | ||||||
|     {{0x87, 0xd7, 0xff}, "117    SkyBlue1          #87d7ff"}, |  | ||||||
|     {{0x87, 0xff, 0x00}, "118    Chartreuse1       #87ff00"}, |  | ||||||
|     {{0x87, 0xff, 0x5f}, "119    LightGreen        #87ff5f"}, |  | ||||||
|     {{0x87, 0xff, 0x87}, "120    LightGreen        #87ff87"}, |  | ||||||
|     {{0x87, 0xff, 0xaf}, "121    PaleGreen1        #87ffaf"}, |  | ||||||
|     {{0x87, 0xff, 0xd7}, "122    Aquamarine1       #87ffd7"}, |  | ||||||
|     {{0x87, 0xff, 0xff}, "123    DarkSlateGray1    #87ffff"}, |  | ||||||
|     {{0xaf, 0x00, 0x00}, "124    Red3              #af0000"}, |  | ||||||
|     {{0xaf, 0x00, 0x5f}, "125    DeepPink4         #af005f"}, |  | ||||||
|     {{0xaf, 0x00, 0x87}, "126    MediumVioletRed   #af0087"}, |  | ||||||
|     {{0xaf, 0x00, 0xaf}, "127    Magenta3          #af00af"}, |  | ||||||
|     {{0xaf, 0x00, 0xd7}, "128    DarkViolet        #af00d7"}, |  | ||||||
|     {{0xaf, 0x00, 0xff}, "129    Purple            #af00ff"}, |  | ||||||
|     {{0xaf, 0x5f, 0x00}, "130    DarkOrange3       #af5f00"}, |  | ||||||
|     {{0xaf, 0x5f, 0x5f}, "131    IndianRed         #af5f5f"}, |  | ||||||
|     {{0xaf, 0x5f, 0x87}, "132    HotPink3          #af5f87"}, |  | ||||||
|     {{0xaf, 0x5f, 0xaf}, "133    MediumOrchid3     #af5faf"}, |  | ||||||
|     {{0xaf, 0x5f, 0xd7}, "134    MediumOrchid      #af5fd7"}, |  | ||||||
|     {{0xaf, 0x5f, 0xff}, "135    MediumPurple2     #af5fff"}, |  | ||||||
|     {{0xaf, 0x87, 0x00}, "136    DarkGoldenrod     #af8700"}, |  | ||||||
|     {{0xaf, 0x87, 0x5f}, "137    LightSalmon3      #af875f"}, |  | ||||||
|     {{0xaf, 0x87, 0x87}, "138    RosyBrown         #af8787"}, |  | ||||||
|     {{0xaf, 0x87, 0xaf}, "139    Grey63            #af87af"}, |  | ||||||
|     {{0xaf, 0x87, 0xd7}, "140    MediumPurple2     #af87d7"}, |  | ||||||
|     {{0xaf, 0x87, 0xff}, "141    MediumPurple1     #af87ff"}, |  | ||||||
|     {{0xaf, 0xaf, 0x00}, "142    Gold3             #afaf00"}, |  | ||||||
|     {{0xaf, 0xaf, 0x5f}, "143    DarkKhaki         #afaf5f"}, |  | ||||||
|     {{0xaf, 0xaf, 0x87}, "144    NavajoWhite3      #afaf87"}, |  | ||||||
|     {{0xaf, 0xaf, 0xaf}, "145    Grey69            #afafaf"}, |  | ||||||
|     {{0xaf, 0xaf, 0xd7}, "146    LightSteelBlue3   #afafd7"}, |  | ||||||
|     {{0xaf, 0xaf, 0xff}, "147    LightSteelBlue    #afafff"}, |  | ||||||
|     {{0xaf, 0xd7, 0x00}, "148    Yellow3           #afd700"}, |  | ||||||
|     {{0xaf, 0xd7, 0x5f}, "149    DarkOliveGreen3   #afd75f"}, |  | ||||||
|     {{0xaf, 0xd7, 0x87}, "150    DarkSeaGreen3     #afd787"}, |  | ||||||
|     {{0xaf, 0xd7, 0xaf}, "151    DarkSeaGreen2     #afd7af"}, |  | ||||||
|     {{0xaf, 0xd7, 0xd7}, "152    LightCyan3        #afd7d7"}, |  | ||||||
|     {{0xaf, 0xd7, 0xff}, "153    LightSkyBlue1     #afd7ff"}, |  | ||||||
|     {{0xaf, 0xff, 0x00}, "154    GreenYellow       #afff00"}, |  | ||||||
|     {{0xaf, 0xff, 0x5f}, "155    DarkOliveGreen2   #afff5f"}, |  | ||||||
|     {{0xaf, 0xff, 0x87}, "156    PaleGreen1        #afff87"}, |  | ||||||
|     {{0xaf, 0xff, 0xaf}, "157    DarkSeaGreen2     #afffaf"}, |  | ||||||
|     {{0xaf, 0xff, 0xd7}, "158    DarkSeaGreen1     #afffd7"}, |  | ||||||
|     {{0xaf, 0xff, 0xff}, "159    PaleTurquoise1    #afffff"}, |  | ||||||
|     {{0xd7, 0x00, 0x00}, "160    Red3              #d70000"}, |  | ||||||
|     {{0xd7, 0x00, 0x5f}, "161    DeepPink3         #d7005f"}, |  | ||||||
|     {{0xd7, 0x00, 0x87}, "162    DeepPink3         #d70087"}, |  | ||||||
|     {{0xd7, 0x00, 0xaf}, "163    Magenta3          #d700af"}, |  | ||||||
|     {{0xd7, 0x00, 0xd7}, "164    Magenta3          #d700d7"}, |  | ||||||
|     {{0xd7, 0x00, 0xff}, "165    Magenta2          #d700ff"}, |  | ||||||
|     {{0xd7, 0x5f, 0x00}, "166    DarkOrange3       #d75f00"}, |  | ||||||
|     {{0xd7, 0x5f, 0x5f}, "167    IndianRed         #d75f5f"}, |  | ||||||
|     {{0xd7, 0x5f, 0x87}, "168    HotPink3          #d75f87"}, |  | ||||||
|     {{0xd7, 0x5f, 0xaf}, "169    HotPink2          #d75faf"}, |  | ||||||
|     {{0xd7, 0x5f, 0xd7}, "170    Orchid            #d75fd7"}, |  | ||||||
|     {{0xd7, 0x5f, 0xff}, "171    MediumOrchid1     #d75fff"}, |  | ||||||
|     {{0xd7, 0x87, 0x00}, "172    Orange3           #d78700"}, |  | ||||||
|     {{0xd7, 0x87, 0x5f}, "173    LightSalmon3      #d7875f"}, |  | ||||||
|     {{0xd7, 0x87, 0x87}, "174    LightPink3        #d78787"}, |  | ||||||
|     {{0xd7, 0x87, 0xaf}, "175    Pink3             #d787af"}, |  | ||||||
|     {{0xd7, 0x87, 0xd7}, "176    Plum3             #d787d7"}, |  | ||||||
|     {{0xd7, 0x87, 0xff}, "177    Violet            #d787ff"}, |  | ||||||
|     {{0xd7, 0xaf, 0x00}, "178    Gold3             #d7af00"}, |  | ||||||
|     {{0xd7, 0xaf, 0x5f}, "179    LightGoldenrod3   #d7af5f"}, |  | ||||||
|     {{0xd7, 0xaf, 0x87}, "180    Tan               #d7af87"}, |  | ||||||
|     {{0xd7, 0xaf, 0xaf}, "181    MistyRose3        #d7afaf"}, |  | ||||||
|     {{0xd7, 0xaf, 0xd7}, "182    Thistle3          #d7afd7"}, |  | ||||||
|     {{0xd7, 0xaf, 0xff}, "183    Plum2             #d7afff"}, |  | ||||||
|     {{0xd7, 0xd7, 0x00}, "184    Yellow3           #d7d700"}, |  | ||||||
|     {{0xd7, 0xd7, 0x5f}, "185    Khaki3            #d7d75f"}, |  | ||||||
|     {{0xd7, 0xd7, 0x87}, "186    LightGoldenrod2   #d7d787"}, |  | ||||||
|     {{0xd7, 0xd7, 0xaf}, "187    LightYellow3      #d7d7af"}, |  | ||||||
|     {{0xd7, 0xd7, 0xd7}, "188    Grey84            #d7d7d7"}, |  | ||||||
|     {{0xd7, 0xd7, 0xff}, "189    LightSteelBlue1   #d7d7ff"}, |  | ||||||
|     {{0xd7, 0xff, 0x00}, "190    Yellow2           #d7ff00"}, |  | ||||||
|     {{0xd7, 0xff, 0x5f}, "191    DarkOliveGreen1   #d7ff5f"}, |  | ||||||
|     {{0xd7, 0xff, 0x87}, "192    DarkOliveGreen1   #d7ff87"}, |  | ||||||
|     {{0xd7, 0xff, 0xaf}, "193    DarkSeaGreen1     #d7ffaf"}, |  | ||||||
|     {{0xd7, 0xff, 0xd7}, "194    Honeydew2         #d7ffd7"}, |  | ||||||
|     {{0xd7, 0xff, 0xff}, "195    LightCyan1        #d7ffff"}, |  | ||||||
|     {{0xff, 0x00, 0x00}, "196    Red1              #ff0000"}, |  | ||||||
|     {{0xff, 0x00, 0x5f}, "197    DeepPink2         #ff005f"}, |  | ||||||
|     {{0xff, 0x00, 0x87}, "198    DeepPink1         #ff0087"}, |  | ||||||
|     {{0xff, 0x00, 0xaf}, "199    DeepPink1         #ff00af"}, |  | ||||||
|     {{0xff, 0x00, 0xd7}, "200    Magenta2          #ff00d7"}, |  | ||||||
|     {{0xff, 0x00, 0xff}, "201    Magenta1          #ff00ff"}, |  | ||||||
|     {{0xff, 0x5f, 0x00}, "202    OrangeRed1        #ff5f00"}, |  | ||||||
|     {{0xff, 0x5f, 0x5f}, "203    IndianRed1        #ff5f5f"}, |  | ||||||
|     {{0xff, 0x5f, 0x87}, "204    IndianRed1        #ff5f87"}, |  | ||||||
|     {{0xff, 0x5f, 0xaf}, "205    HotPink           #ff5faf"}, |  | ||||||
|     {{0xff, 0x5f, 0xd7}, "206    HotPink           #ff5fd7"}, |  | ||||||
|     {{0xff, 0x5f, 0xff}, "207    MediumOrchid1     #ff5fff"}, |  | ||||||
|     {{0xff, 0x87, 0x00}, "208    DarkOrange        #ff8700"}, |  | ||||||
|     {{0xff, 0x87, 0x5f}, "209    Salmon1           #ff875f"}, |  | ||||||
|     {{0xff, 0x87, 0x87}, "210    LightCoral        #ff8787"}, |  | ||||||
|     {{0xff, 0x87, 0xaf}, "211    PaleVioletRed1    #ff87af"}, |  | ||||||
|     {{0xff, 0x87, 0xd7}, "212    Orchid2           #ff87d7"}, |  | ||||||
|     {{0xff, 0x87, 0xff}, "213    Orchid1           #ff87ff"}, |  | ||||||
|     {{0xff, 0xaf, 0x00}, "214    Orange1           #ffaf00"}, |  | ||||||
|     {{0xff, 0xaf, 0x5f}, "215    SandyBrown        #ffaf5f"}, |  | ||||||
|     {{0xff, 0xaf, 0x87}, "216    LightSalmon1      #ffaf87"}, |  | ||||||
|     {{0xff, 0xaf, 0xaf}, "217    LightPink1        #ffafaf"}, |  | ||||||
|     {{0xff, 0xaf, 0xd7}, "218    Pink1             #ffafd7"}, |  | ||||||
|     {{0xff, 0xaf, 0xff}, "219    Plum1             #ffafff"}, |  | ||||||
|     {{0xff, 0xd7, 0x00}, "220    Gold1             #ffd700"}, |  | ||||||
|     {{0xff, 0xd7, 0x5f}, "221    LightGoldenrod2   #ffd75f"}, |  | ||||||
|     {{0xff, 0xd7, 0x87}, "222    LightGoldenrod2   #ffd787"}, |  | ||||||
|     {{0xff, 0xd7, 0xaf}, "223    NavajoWhite1      #ffd7af"}, |  | ||||||
|     {{0xff, 0xd7, 0xd7}, "224    MistyRose1        #ffd7d7"}, |  | ||||||
|     {{0xff, 0xd7, 0xff}, "225    Thistle1          #ffd7ff"}, |  | ||||||
|     {{0xff, 0xff, 0x00}, "226    Yellow1           #ffff00"}, |  | ||||||
|     {{0xff, 0xff, 0x5f}, "227    LightGoldenrod1   #ffff5f"}, |  | ||||||
|     {{0xff, 0xff, 0x87}, "228    Khaki1            #ffff87"}, |  | ||||||
|     {{0xff, 0xff, 0xaf}, "229    Wheat1            #ffffaf"}, |  | ||||||
|     {{0xff, 0xff, 0xd7}, "230    Cornsilk1         #ffffd7"}, |  | ||||||
|     {{0xff, 0xff, 0xff}, "231    Grey100           #ffffff"}, |  | ||||||
|     {{0x08, 0x08, 0x08}, "232    Grey3             #080808"}, |  | ||||||
|     {{0x12, 0x12, 0x12}, "233    Grey7             #121212"}, |  | ||||||
|     {{0x1c, 0x1c, 0x1c}, "234    Grey11            #1c1c1c"}, |  | ||||||
|     {{0x26, 0x26, 0x26}, "235    Grey15            #262626"}, |  | ||||||
|     {{0x30, 0x30, 0x30}, "236    Grey19            #303030"}, |  | ||||||
|     {{0x3a, 0x3a, 0x3a}, "237    Grey23            #3a3a3a"}, |  | ||||||
|     {{0x44, 0x44, 0x44}, "238    Grey27            #444444"}, |  | ||||||
|     {{0x4e, 0x4e, 0x4e}, "239    Grey30            #4e4e4e"}, |  | ||||||
|     {{0x58, 0x58, 0x58}, "240    Grey35            #585858"}, |  | ||||||
|     {{0x62, 0x62, 0x62}, "241    Grey39            #626262"}, |  | ||||||
|     {{0x6c, 0x6c, 0x6c}, "242    Grey42            #6c6c6c"}, |  | ||||||
|     {{0x76, 0x76, 0x76}, "243    Grey46            #767676"}, |  | ||||||
|     {{0x80, 0x80, 0x80}, "244    Grey50            #808080"}, |  | ||||||
|     {{0x8a, 0x8a, 0x8a}, "245    Grey54            #8a8a8a"}, |  | ||||||
|     {{0x94, 0x94, 0x94}, "246    Grey58            #949494"}, |  | ||||||
|     {{0x9e, 0x9e, 0x9e}, "247    Grey62            #9e9e9e"}, |  | ||||||
|     {{0xa8, 0xa8, 0xa8}, "248    Grey66            #a8a8a8"}, |  | ||||||
|     {{0xb2, 0xb2, 0xb2}, "249    Grey70            #b2b2b2"}, |  | ||||||
|     {{0xbc, 0xbc, 0xbc}, "250    Grey74            #bcbcbc"}, |  | ||||||
|     {{0xc6, 0xc6, 0xc6}, "251    Grey78            #c6c6c6"}, |  | ||||||
|     {{0xd0, 0xd0, 0xd0}, "252    Grey82            #d0d0d0"}, |  | ||||||
|     {{0xda, 0xda, 0xda}, "253    Grey85            #dadada"}, |  | ||||||
|     {{0xe4, 0xe4, 0xe4}, "254    Grey89            #e4e4e4"}, |  | ||||||
|     {{0xee, 0xee, 0xee}, "255    Grey93            #eeeeee"}, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) { |  | ||||||
|   size_t i; |  | ||||||
|   printf("BG FG BB BF XTERM NAME              HEX\n"); |  | ||||||
|   for (i = 0; i < 256; ++i) { |  | ||||||
|     printf("\e[48;5;%dm  \e[0m \e[38;5;%dm██\e[0m \e[1;48;5;%dm  " |  | ||||||
|            "\e[0m \e[1;38;5;%dm██\e[0m %-6hhu%-18s#%02hhx%02hhx%02hhx\n", |  | ||||||
|            i, i, i, i, i, IndexDoubleNulString(kXtermName, i), kXtermRgb[i].r, |  | ||||||
|            kXtermRgb[i].g, kXtermRgb[i].b); |  | ||||||
|   } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue