/* * (C)opyright MMVI-MMVII Anselm R. Garbe * (C)opyright MMVII Robert Manea * See LICENSE file for license details. * */ #include "dzen.h" #include #include #include #include #include #include #define ONEMASK ((size_t)(-1) / 0xFF) void * emalloc(unsigned int size) { void *res = malloc(size); if(!res) eprint("fatal: could not malloc() %u bytes\n", size); return res; } void eprint(const char *errstr, ...) { va_list ap; va_start(ap, errstr); vfprintf(stderr, errstr, ap); va_end(ap); exit(EXIT_FAILURE); } char * estrdup(const char *str) { void *res = strdup(str); if(!res) eprint("fatal: could not malloc() %u bytes\n", strlen(str)); return res; } void spawn(const char *arg) { static const char *shell = NULL; if(!shell && !(shell = getenv("SHELL"))) shell = "/bin/sh"; if(!arg) return; /* The double-fork construct avoids zombie processes and keeps the code * clean from stupid signal handlers. */ if(fork() == 0) { if(fork() == 0) { setsid(); execl(shell, shell, "-c", arg, (char *)NULL); fprintf(stderr, "dzen: execl '%s -c %s'", shell, arg); perror(" failed"); } exit(0); } wait(0); } /* http://www.daemonology.net/blog/2008-06-05-faster-utf8-strlen.html */ size_t strlen_utf8(const char * _s) { const char * s; size_t count = 0; size_t u; unsigned char b; /* Handle any initial misaligned bytes. */ for (s = _s; (uintptr_t)(s) & (sizeof(size_t) - 1); s++) { b = *s; /* Exit if we hit a zero byte. */ if (b == '\0') goto done; /* Is this byte NOT the first byte of a character? */ count += (b >> 7) & ((~b) >> 6); } /* Handle complete blocks. */ for (; ; s += sizeof(size_t)) { /* Prefetch 256 bytes ahead. */ __builtin_prefetch(&s[256], 0, 0); /* Grab 4 or 8 bytes of UTF-8 data. */ u = *(size_t *)(s); /* Exit the loop if there are any zero bytes. */ if ((u - ONEMASK) & (~u) & (ONEMASK * 0x80)) break; /* Count bytes which are NOT the first byte of a character. */ u = ((u & (ONEMASK * 0x80)) >> 7) & ((~u) >> 6); count += (u * ONEMASK) >> ((sizeof(size_t) - 1) * 8); } /* Take care of any left-over bytes. */ for (; ; s++) { b = *s; /* Exit if we hit a zero byte. */ if (b == '\0') break; /* Is this byte NOT the first byte of a character? */ count += (b >> 7) & ((~b) >> 6); } done: return ((s - _s) - count); }