dstr *dstr_split_len(const char *str, size_t length, const char *sep, size_t seplength, int *count) { int slots = 5, i, nelems = 0, start = 0; dstr *tokens; /* FIXME */ if (str == NULL || sep == NULL) return NULL; if (length < 0 || seplength < 1) return NULL; if ((tokens = ALLOC(slots * sizeof *tokens)) == NULL) return NULL; if (length == 0) { *count = 0; return tokens; } for (i = 0; i < length - seplength + 1; ++i) { /* make sure there is room for the next and final ones */ if (slots < nelems + 2) { slots *= 2; if (RESIZE(tokens, slots * sizeof *tokens) == NULL) goto err; } if ((seplength == 1 && str[i] == sep[0]) || !memcmp(str + i, sep, seplength)) { if ((tokens[nelems] = dstr_new_len(str + start, i - start)) == NULL) goto err; ++nelems; start = i + seplength; i += seplength - 1; } } /* add the final one */ if ((tokens[nelems] = dstr_new_len(str + start, length - start)) == NULL) goto err; ++nelems; *count = nelems; return tokens; err: for (i = 0; i < nelems; ++i) dstr_free(tokens[i]); FREE(tokens); *count = 0; return NULL; }
dstr dstr_new(const char *str) { size_t length = str ? strlen(str) : 0; return dstr_new_len(str, length); }
dstr *dstr_split_args(const char *line, int *argc) { const char *p = line; dstr current = NULL; dstr *argv = NULL; *argc = 0; for (;;) { while (*p && isspace(*p)) ++p; if (*p) { int inq = 0; /* 1 if in quotes */ int insq = 0; /* 1 if in single quotes */ int done = 0; if (current == NULL) current = dstr_new_len("", 0); while (!done) { /* FIXME */ if (inq) { if (*p == '\\' && *(p + 1) == 'x' && is_hex_digit(*(p + 2)) && is_hex_digit(*(p + 3))) { unsigned char byte = 16 * hex_digit_to_int(*(p + 2)) + hex_digit_to_int(*(p + 3)); p += 3; current = dstr_cat_len(current, (char *)&byte, 1); } else if (*p == '\\' && *(p + 1)) { char c; ++p; switch (*p) { case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; default: c = *p; break; } current = dstr_cat_len(current, &c, 1); } else if (*p == '"') { /* closing quote must be followed by a space or not at all */ if (*(p + 1) && !isspace(*(p + 1))) goto err; done = 1; /* unterminated quotes */ } else if (*p == '\0') goto err; else current = dstr_cat_len(current, p, 1); } else if (insq) { if (*p == '\\' && *(p + 1) == '\'') { ++p; current = dstr_cat_len(current, "'", 1); } else if (*p == '\'') { /* closing quote must be followed by a space or not at all */ if (*(p + 1) && !isspace(*(p + 1))) goto err; done = 1; /* unterminated quotes */ } else if (*p == '\0') goto err; else current = dstr_cat_len(current, p, 1); } else switch (*p) { case ' ': case '\0': case '\n': case '\r': case '\t': done = 1; break; case '"': inq = 1; break; case '\'': insq = 1; break; default: current = dstr_cat_len(current, p, 1); break; } if (*p) ++p; } if (RESIZE(argv, (*argc + 1) * sizeof (char *)) == NULL) goto err; argv[*argc] = current; ++*argc; current = NULL; } else return argv; } err: { int i; for (i = 0; i < *argc; ++i) dstr_free(argv[i]); FREE(argv); if (current) dstr_free(current); return NULL; } }
static int impvbaw_exec(void *data, void *data2) { RAII_VAR(struct msg *, msg, (struct msg *)data, msg_decr); Quote *quote = (Quote *)msg->data; struct msgs *out = (struct msgs *)data2; dstr contract; float last; char *p; table_node_t node; contract = dstr_new(quote->thyquote.m_cHYDM); if (!strcmp(contract, "") || (fabs(quote->thyquote.m_dZXJ) <= 0.000001 && fabs(quote->thyquote.m_dMRJG1) <= 0.000001 && fabs(quote->thyquote.m_dMCJG1) <= 0.000001)) { xcb_log(XCB_LOG_WARNING, "Invalid quote: '%d,%d,%s,%.2f,%.2f,%.2f'", quote->thyquote.m_nTime, quote->m_nMSec, contract, quote->thyquote.m_dZXJ, quote->thyquote.m_dMRJG1, quote->thyquote.m_dMCJG1); goto end; } /* FIXME */ if (!strncasecmp(contract, "IO", 2) || !strncasecmp(contract, "HO", 2) || !strncasecmp(contract, "00", 2) || !strncasecmp(contract, "60", 2)) goto end; last = quote->thyquote.m_dZXJ; if ((p = strrchr(contract, 'C')) == NULL) p = strrchr(contract, 'P'); /* FIXME: option quote */ if (p && p != contract && p != contract + dstr_length(contract) - 1 && ((*(p - 1) == '-' && *(p + 1) == '-') || (isdigit(*(p - 1)) && isdigit(*(p + 1))))) { dstr spotname, type, strike; float spot; struct prices *prices; double expiry, vol, vol2, vol3; struct tm lt; char *res; spotname = *(p - 1) == '-' ? dstr_new_len(contract, p - contract - 1) : dstr_new_len(contract, p - contract); type = dstr_new_len(p, 1); strike = *(p + 1) == '-' ? dstr_new_len(p + 2, contract + dstr_length(contract) - p - 2) : dstr_new_len(p + 1, contract + dstr_length(contract) - p - 1); table_rwlock_rdlock(spots); if ((node = table_find(spots, spotname)) == NULL) { table_rwlock_unlock(spots); dstr_free(strike); dstr_free(type); dstr_free(spotname); goto end; } spot = table_node_float(node); table_rwlock_unlock(spots); if (fabs(spot) <= 0.000001) { xcb_log(XCB_LOG_WARNING, "The price of spot '%s' be zero", spotname); dstr_free(strike); dstr_free(type); dstr_free(spotname); goto end; } table_lock(optns); if ((node = table_find(optns, contract)) == NULL) { if (NEW(prices)) { prices->prelast = last; prices->prebid1 = quote->thyquote.m_dMRJG1; prices->preask1 = quote->thyquote.m_dMCJG1; prices->prespot = spot; table_insert(optns, dstr_new(contract), prices); } else xcb_log(XCB_LOG_WARNING, "Error allocating memory for prices"); } else { prices = (struct prices *)table_node_value(node); if (fabs(prices->prelast - last) <= 0.000001 && fabs(prices->prebid1 - quote->thyquote.m_dMRJG1) <= 0.000001 && fabs(prices->preask1 - quote->thyquote.m_dMCJG1) <= 0.000001 && fabs(prices->prespot - spot) <= 0.000001) { table_unlock(optns); dstr_free(strike); dstr_free(type); dstr_free(spotname); goto end; } else { prices->prelast = last; prices->prebid1 = quote->thyquote.m_dMRJG1; prices->preask1 = quote->thyquote.m_dMCJG1; prices->prespot = spot; } } table_unlock(optns); if ((node = table_find(expiries, contract))) expiry = table_node_double(node); else { char *month; struct timeval tv; int diff; xcb_log(XCB_LOG_WARNING, "No exact expiry date for '%s'", contract); month = spotname + dstr_length(spotname) - 2; gettimeofday(&tv, NULL); if ((diff = atoi(month) - localtime_r(&tv.tv_sec, <)->tm_mon - 1) < 0) diff += 12; if (diff == 0) diff = 1; expiry = diff / 12.0; } /* FIXME: last price */ if (fabs(last) <= 0.000001) vol = NAN; else vol = impv_baw(spot, atof(strike), r, r, expiry, last, !strcasecmp(type, "C") ? AMER_CALL : AMER_PUT); /* FIXME: bid price 1 */ if (fabs(quote->thyquote.m_dMRJG1) <= 0.000001) vol2 = NAN; else if (fabs(quote->thyquote.m_dMRJG1 - last) <= 0.000001) vol2 = vol; else vol2 = impv_baw(spot, atof(strike), r, r, expiry, quote->thyquote.m_dMRJG1, !strcasecmp(type, "C") ? AMER_CALL : AMER_PUT); /* FIXME: ask price 1 */ if (fabs(quote->thyquote.m_dMCJG1) <= 0.000001) vol3 = NAN; else if (fabs(quote->thyquote.m_dMCJG1 - last) <= 0.000001) vol3 = vol; else vol3 = impv_baw(spot, atof(strike), r, r, expiry, quote->thyquote.m_dMCJG1, !strcasecmp(type, "C") ? AMER_CALL : AMER_PUT); if ((res = ALLOC(512))) { time_t t = (time_t)quote->thyquote.m_nTime; char datestr[64]; strftime(datestr, sizeof datestr, "%F %T", localtime_r(&t, <)); snprintf(res, 512, "IMPVBAW,%s.%03d,%s|%.2f,%f,%.2f,%f,%.2f,%f,%.2f", datestr, quote->m_nMSec, contract, last, vol, quote->thyquote.m_dMRJG1, vol2, quote->thyquote.m_dMCJG1, vol3, spot); out2rmp(res); snprintf(res, 512, "IMPVBAW,%d,%d,%s,%.2f,%f,%.2f,%f,%.2f,%f,%.2f,%s,%s,%s,%f,%f,%d,0,0", quote->thyquote.m_nTime, quote->m_nMSec, contract, last, vol, quote->thyquote.m_dMRJG1, vol2, quote->thyquote.m_dMCJG1, vol3, spot, spotname, type, strike, r, expiry, quote->thyquote.m_nCJSL); if (out2msgs(res, out) == -1) FREE(res); } else xcb_log(XCB_LOG_WARNING, "Error allocating memory for result"); dstr_free(strike); dstr_free(type); dstr_free(spotname); /* future quote */ } else { table_rwlock_wrlock(spots); if ((node = table_find(spots, contract)) == NULL) { if ((node = table_insert_raw(spots, contract))) table_set_float(node, last); } else { table_set_float(node, last); dstr_free(contract); } table_rwlock_unlock(spots); return 0; } end: dstr_free(contract); return 0; }
static inline void load_config(void) { /* FIXME */ if ((cfg = config_load("/etc/xcb/vxo.conf"))) { char *cat = category_browse(cfg, NULL); struct variable *var; while (cat) { if (!strcasecmp(cat, "general")) { struct variable *var = variable_browse(cfg, cat); while (var) { if (!strcasecmp(var->name, "inmsg")) { if (strcmp(var->value, "")) inmsg = var->value; } else xcb_log(XCB_LOG_WARNING, "Unknown variable '%s' in " "category '%s' of vxo.conf", var->name, cat); var = var->next; } } else if (!strcasecmp(cat, "expiries")) { var = variable_browse(cfg, cat); while (var) { char *p; if ((p = strrchr(var->name, 'C')) == NULL) p = strrchr(var->name, 'P'); if (p && p != var->name && p != var->name + strlen(var->name) - 1 && ((*(p - 1) == '-' && *(p + 1) == '-') || (isdigit(*(p - 1)) && isdigit(*(p + 1))))) { dstr spotname, strike; struct pd *pd; struct scp *scp; spotname = *(p - 1) == '-' ? dstr_new_len(var->name, p - var->name - 1) : dstr_new_len(var->name, p - var->name); strike = *(p + 1) == '-' ? dstr_new_len(p + 2, var->name + strlen(var->name) - p - 2) : dstr_new_len(p + 1, var->name + strlen(var->name) - p - 1); if ((pd = table_get_value(spots, spotname)) == NULL) { if (NEW(scp)) { scp->strike = atof(strike); scp->cvol = scp->pvol = NAN; scp->cvol2 = scp->pvol2 = NAN; scp->cvol3 = scp->pvol3 = NAN; if (NEW(pd)) { pd->prevxo = pd->prevxo2 = pd->prevxo3 = NAN; pd->sep = *(p - 1) == '-' ? "-" : ""; pd->dlist = dlist_new(NULL, scpfree); dlist_insert_tail(pd->dlist, scp); table_insert(spots, spotname, pd); } else FREE(scp); } else dstr_free(spotname); } else { dlist_iter_t iter = dlist_iter_new(pd->dlist, DLIST_START_HEAD); dlist_node_t node; while ((node = dlist_next(iter))) { scp = (struct scp *)dlist_node_value(node); if (scp->strike > atof(strike) || fabs(scp->strike - atof(strike)) <= 0.000001) break; } dlist_iter_free(&iter); if (node == NULL || scp->strike > atof(strike)) { if (NEW(scp)) { scp->strike = atof(strike); scp->cvol = scp->pvol = NAN; scp->cvol2 = scp->pvol2 = NAN; scp->cvol3 = scp->pvol3 = NAN; } if (node == NULL) dlist_insert_tail(pd->dlist, scp); else dlist_insert(pd->dlist, node, scp, 0); } dstr_free(spotname); } dstr_free(strike); } var = var->next; } } cat = category_browse(cfg, cat); } } }