ph_hook_point_t *ph_hook_point_get(ph_string_t *name, bool create) { ph_hook_point_t *hp = 0; ck_rwlock_read_lock(&rwlock); { ph_ht_lookup(&hook_hash, &name, &hp, false); } ck_rwlock_read_unlock(&rwlock); if (hp || !create) { return hp; } ck_rwlock_write_lock(&rwlock); { // Look again: someone may have populated while we were unlocked ph_ht_lookup(&hook_hash, &name, &hp, false); if (!hp) { hp = ph_mem_alloc(mt.hookpoint); if (hp) { if (ph_ht_set(&hook_hash, &name, &hp) != PH_OK) { ph_mem_free(mt.hookpoint, hp); hp = NULL; } } } } ck_rwlock_write_unlock(&rwlock); return hp; }
// Called when an ARES socket is ready static void process_ares(ph_job_t *job, ph_iomask_t why, void *data) { ph_dns_channel_t *chan = data; ares_socket_t fd; ares_socket_t rfd = ARES_SOCKET_BAD; ares_socket_t wfd = ARES_SOCKET_BAD; fd = job->fd; if (why & PH_IOMASK_READ) { rfd = job->fd; } if (why & PH_IOMASK_WRITE) { wfd = job->fd; } pthread_mutex_lock(&chan->chanlock); ares_process_fd(chan->chan, rfd, wfd); if (ph_ht_lookup(&chan->sock_map, &fd, &job, false) == PH_OK && ph_job_get_kmask(job) == 0) { // Didn't delete it, but didn't reschedule it, so do that now apply_mask(chan, job, job->mask ? job->mask : PH_IOMASK_READ); } pthread_mutex_unlock(&chan->chanlock); }
/* called when ares wants to change the event mask */ static void sock_state_cb(void *data, ares_socket_t socket_fd, int readable, int writable) { ph_dns_channel_t *chan = data; ph_job_t *job; ph_iomask_t mask = 0; if (readable) { mask |= PH_IOMASK_READ; } if (writable) { mask |= PH_IOMASK_WRITE; } if (ph_ht_lookup(&chan->sock_map, &socket_fd, &job, false) != PH_OK) { ph_panic("job for socket %d was not found in ares sock_state_cb", socket_fd); } if (mask) { apply_mask(chan, job, mask); } else { ph_job_set_nbio(job, 0, NULL); // We're done with this guy, remove it ph_ht_del(&chan->sock_map, &socket_fd); ph_mem_free(mt.job, job); } }
ph_variant_t *ph_var_object_get(ph_variant_t *obj, ph_string_t *key) { ph_result_t res; ph_variant_t *val; if (obj->type != PH_VAR_OBJECT) { return 0; } res = ph_ht_lookup(&obj->u.oval, &key, &val, false); if (res != PH_OK) { return 0; } return val; }
int ph_vprintf_core(void *print_arg, const struct ph_vprintf_funcs *print_funcs, const char *fmt0, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ int n, n2; /* handy integers (short term usage) */ char *cp; /* handy char pointer (short term usage) */ int flags; /* flags as above */ int ret; /* return value accumulator */ int width; /* width from format (%8d), or 0 */ int prec; /* precision from format; <0 for N/A */ char sign; /* sign prefix (' ', '+', '-', or \0) */ wchar_t wc; mbstate_t ps; #ifdef FLOATING_POINT /* * We can decompose the printed representation of floating * point numbers into several parts, some of which may be empty: * * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ * A B ---C--- D E F * * A: 'sign' holds this value if present; '\0' otherwise * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal * C: cp points to the string MMMNNN. Leading and trailing * zeros are not in the string and must be added. * D: expchar holds this character; '\0' if no exponent, e.g. %f * F: at least two digits for decimal, at least one digit for hex */ const char *decimal_point = #ifdef USE_LOCALE NULL #else "." #endif ; int signflag; /* true if float is negative */ union { /* floating point arguments %[aAeEfFgG] */ double dbl; long double ldbl; } fparg; int expt; /* integer value of exponent */ char expchar = 0; /* exponent character: [eEpP\0] */ char *dtoaend; /* pointer to end of converted digits */ int expsize = 0; /* character count for expstr */ int lead = 0; /* sig figs before decimal or group sep */ int ndig = 0; /* actual number of digits returned by dtoa */ char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ char *dtoaresult = NULL; #endif uintmax_t _umax; /* integer arguments %[diouxX] */ enum { OCT, DEC, HEX } base; /* base for %[diouxX] conversion */ int dprec; /* a copy of prec if %[diouxX], 0 otherwise */ int realsz; /* field size expanded by dprec */ int size; /* size of converted field or string */ const char *xdigs = xdigs_lower; /* digits for %[xX] conversion */ char buf[BUF]; /* buffer with space for digits of uintmax_t */ char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */ union arg *argtable; /* args, built due to positional arg */ union arg statargtable[STATIC_ARG_TBL_SIZE]; size_t argtablesiz; int nextarg; /* 1-based argument index */ va_list orgap; /* original argument pointer */ #ifdef PRINTF_WIDE_CHAR char *convbuf; /* buffer for wide to multi-byte conversion */ #endif bool print_error = false; /* * BEWARE, these `goto error' on error, and PAD uses `n'. */ #define PRINT(ptr, len) do { \ if (len > 0 && !print_funcs->print(print_arg, ptr, len)) { \ print_error = true; \ goto error; \ } \ } while (0) #define PAD(howmany, with) do { \ if ((n = (howmany)) > 0) { \ while (n > PADSIZE) { \ PRINT(with, PADSIZE); \ n -= PADSIZE; \ } \ PRINT(with, n); \ } \ } while (0) #define PRINTANDPAD(p, ep, len, with) do { \ n2 = (ep) - (p); \ if (n2 > (len)) \ n2 = (len); \ if (n2 > 0) \ PRINT((p), n2); \ PAD((len) - (n2 > 0 ? n2 : 0), (with)); \ } while(0) #define FLUSH() do { \ if (print_funcs->flush && !print_funcs->flush(print_arg)) { \ print_error = true; \ goto error; \ } \ } while (0) /* * To extend shorts properly, we need both signed and unsigned * argument extraction methods. */ #define SARG() \ ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \ flags&LLONGINT ? GETARG(long long) : \ flags&LONGINT ? GETARG(long) : \ flags&PTRINT ? GETARG(ptrdiff_t) : \ flags&SIZEINT ? GETARG(ssize_t) : \ flags&SHORTINT ? (short)GETARG(int) : \ flags&CHARINT ? (__signed char)GETARG(int) : \ GETARG(int))) #define UARG() \ ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \ flags&LLONGINT ? GETARG(unsigned long long) : \ flags&LONGINT ? GETARG(unsigned long) : \ flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \ flags&SIZEINT ? GETARG(size_t) : \ flags&SHORTINT ? (unsigned short)GETARG(int) : \ flags&CHARINT ? (unsigned char)GETARG(int) : \ GETARG(unsigned int))) /* * Append a digit to a value and check for overflow. */ #define APPEND_DIGIT(val, dig) do { \ if ((val) > INT_MAX / 10) \ goto overflow; \ (val) *= 10; \ if ((val) > INT_MAX - to_digit((dig))) \ goto overflow; \ (val) += to_digit((dig)); \ } while (0) /* * Get * arguments, including the form *nn$. Preserve the nextarg * that the argument can be gotten once the type is determined. */ #define GETASTER(val) \ n2 = 0; \ cp = fmt; \ while (is_digit(*cp)) { \ APPEND_DIGIT(n2, *cp); \ cp++; \ } \ if (*cp == '$') { \ int hold = nextarg; \ if (argtable == NULL) { \ argtable = statargtable; \ __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \ } \ nextarg = n2; \ val = GETARG(int); \ nextarg = hold; \ fmt = ++cp; \ } else { \ val = GETARG(int); \ } /* * Get the argument indexed by nextarg. If the argument table is * built, use it to get the argument. If its not, get the next * argument (and arguments must be gotten sequentially). */ #define GETARG(type) \ ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ (nextarg++, va_arg(ap, type))) fmt = (char *)fmt0; argtable = NULL; nextarg = 1; va_copy(orgap, ap); ret = 0; #ifdef PRINTF_WIDE_CHAR convbuf = NULL; #endif memset(&ps, 0, sizeof(ps)); /* * Scan the format for conversions (`%' character). */ for (;;) { cp = fmt; while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) { fmt += n; if (wc == '%' || wc == '`') { fmt--; break; } } if (fmt != cp) { ptrdiff_t m = fmt - cp; if (m < 0 || m > INT_MAX - ret) goto overflow; PRINT(cp, m); ret += m; } if (n <= 0) goto done; flags = 0; dprec = 0; width = 0; prec = -1; sign = '\0'; ox[1] = '\0'; /* check for phenom specials */ if (fmt[0] == '`') { if (fmt[1] == '`') { /* we just print a literal ` */ PRINT(fmt, 1); fmt += 2; continue; } if (fmt[1] != 'P') { /* some regular backtick enclosed text */ PRINT(fmt, 1); fmt++; continue; } switch (fmt[2]) { case '{': { char *term; void *object; struct formatter *f = NULL; ph_string_t key, *keyptr = &key; fmt += 3; term = strstr(fmt, ":%p}"); if (!term) { break; } object = GETARG(void*); pthread_once(&once_init, init_vprintf); ph_string_init_claim(&key, PH_STRING_STATIC, fmt, term - fmt, term - fmt); pthread_rwlock_rdlock(&formatter_lock); ph_ht_lookup(&formatters, &keyptr, (void*)&f, false); pthread_rwlock_unlock(&formatter_lock); if (f && f->func) { ret += f->func(f->farg, object, print_arg, print_funcs); } else { PRINT("INVALID:", 8); PRINT(fmt, term - fmt); ret += 8 + (term - fmt); } fmt = term + 4; continue; } case 'e': /* "`Pe%d" errno formatted as string */ if (fmt[3] == '%' && fmt[4] == 'd') { char ebuf[128]; int err = GETARG(int); cp = (char*)ph_strerror_r(err, ebuf, sizeof(ebuf)); size = strlen(cp); fmt += 5; PRINT(cp, size); ret += size; continue; } break; case 's': { uint32_t len; ph_string_t *str = NULL; if (!memcmp("%p", fmt + 3, 2)) { str = GETARG(void*); len = str->len; fmt += 5; } else if (!memcmp("%d%p", fmt + 3, 4)) { len = GETARG(int); str = GETARG(void*); len = MIN(len, str->len); fmt += 7; } else { // invalid break;