static GMQCC_INLINE ast_expression *fold_op_mul(fold_t *fold, ast_value *a, ast_value *b) { if (isfloat(a)) { if (isvector(b)) { if (fold_can_2(a, b)) return fold_constgen_vector(fold, vec3_mulvf(fold_immvalue_vector(b), fold_immvalue_float(a))); } else { if (fold_can_2(a, b)) return fold_constgen_float(fold, fold_immvalue_float(a) * fold_immvalue_float(b)); } } else if (isvector(a)) { if (isfloat(b)) { if (fold_can_2(a, b)) return fold_constgen_vector(fold, vec3_mulvf(fold_immvalue_vector(a), fold_immvalue_float(b))); } else { if (fold_can_2(a, b)) { return fold_constgen_float(fold, vec3_mulvv(fold_immvalue_vector(a), fold_immvalue_vector(b))); } else if (OPTS_OPTIMIZATION(OPTIM_VECTOR_COMPONENTS) && fold_can_1(a)) { ast_expression *out; if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(a), b, "xyz"))) return out; if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(a), b, "yxz"))) return out; if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(a), b, "zxy"))) return out; } else if (OPTS_OPTIMIZATION(OPTIM_VECTOR_COMPONENTS) && fold_can_1(b)) { ast_expression *out; if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(b), a, "xyz"))) return out; if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(b), a, "yxz"))) return out; if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(b), a, "zxy"))) return out; } } } return NULL; }
static int numeric_compare(const SpnValue *lhs, const SpnValue *rhs) { assert(isnum(lhs) && isnum(rhs)); if (isfloat(lhs)) { if (isfloat(rhs)) { return floatvalue(lhs) < floatvalue(rhs) ? -1 : floatvalue(lhs) > floatvalue(rhs) ? +1 : 0; } else { return floatvalue(lhs) < intvalue(rhs) ? -1 : floatvalue(lhs) > intvalue(rhs) ? +1 : 0; } } else { if (isfloat(rhs)) { return intvalue(lhs) < floatvalue(rhs) ? -1 : intvalue(lhs) > floatvalue(rhs) ? +1 : 0; } else { return intvalue(lhs) < intvalue(rhs) ? -1 : intvalue(lhs) > intvalue(rhs) ? +1 : 0; } } }
static int numeric_equal(const SpnValue *lhs, const SpnValue *rhs) { assert(isnum(lhs) && isnum(rhs)); if (isfloat(lhs)) { return isfloat(rhs) ? floatvalue(lhs) == floatvalue(rhs) : floatvalue(lhs) == intvalue(rhs); } else { return isfloat(rhs) ? intvalue(lhs) == floatvalue(rhs) : intvalue(lhs) == intvalue(rhs); } }
/* Return the product of two expressions */ static exp_t * prod(exp_t *a1, exp_t *a2) { exp_t *res; CHKNUM(a1, *); CHKNUM(a2, *); if (isfloat(a1) || isfloat(a2)) res = nfloat(VALUE(a1) * VALUE(a2)); else res = nrat(NUMER(a1) * NUMER(a2), DENOM(a1) * DENOM(a2)); return res; }
static GMQCC_INLINE ast_expression *fold_op_cmp(fold_t *fold, ast_value *a, ast_value *b, bool ne) { if (fold_can_2(a, b)) { if (isfloat(a) && isfloat(b)) { float la = fold_immvalue_float(a); float lb = fold_immvalue_float(b); return (ast_expression*)fold->imm_float[!(ne ? la == lb : la != lb)]; } if (isvector(a) && isvector(b)) { vec3_t la = fold_immvalue_vector(a); vec3_t lb = fold_immvalue_vector(b); return (ast_expression*)fold->imm_float[!(ne ? vec3_cmp(la, lb) : !vec3_cmp(la, lb))]; } } return NULL; }
void retcode(Tree p) { Type ty; if (p == NULL) { if (events.returns) apply(events.returns, cfunc, NULL); return; } p = pointer(p); ty = assign(freturn(cfunc->type), p); if (ty == NULL) { error("illegal return type; found `%t' expected `%t'\n", p->type, freturn(cfunc->type)); return; } p = cast(p, ty); if (retv) { if (iscallb(p)) p = tree(RIGHT, p->type, tree(CALL+B, p->type, p->kids[0]->kids[0], idtree(retv)), rvalue(idtree(retv))); else { Type ty = retv->type->type; assert(isstruct(ty)); if (ty->u.sym->u.s.cfields) { ty->u.sym->u.s.cfields = 0; p = asgntree(ASGN, rvalue(idtree(retv)), p); ty->u.sym->u.s.cfields = 1; } else p = asgntree(ASGN, rvalue(idtree(retv)), p); } walk(p, 0, 0); if (events.returns) apply(events.returns, cfunc, rvalue(idtree(retv))); return; } if (events.returns) { Symbol t1 = genident(AUTO, p->type, level); addlocal(t1); walk(asgn(t1, p), 0, 0); apply(events.returns, cfunc, idtree(t1)); p = idtree(t1); } if (!isfloat(p->type)) p = cast(p, promote(p->type)); if (isptr(p->type)) { Symbol q = localaddr(p); if (q && (q->computed || q->generated)) warning("pointer to a %s is an illegal return value\n", q->scope == PARAM ? "parameter" : "local"); else if (q) warning("pointer to %s `%s' is an illegal return value\n", q->scope == PARAM ? "parameter" : "local", q->name); } walk(tree(mkop(RET,p->type), p->type, p, NULL), 0, 0); }
/* Return the division of two expressions */ static exp_t * divs(exp_t *a1, exp_t *a2) { exp_t *res; CHKNUM(a1, /); CHKNUM(a2, /); if (VALUE(a2) == 0) everr("/: argument is divided by zero", a1); if (isfloat(a1) || isfloat(a2)) res = nfloat(VALUE(a1) / VALUE(a2)); else res = nrat(NUMER(a1) * DENOM(a2), NUMER(a2) * DENOM(a1)); return res; }
static GMQCC_INLINE int fold_cond(ir_value *condval, ast_function *func, ast_ifthen *branch) { if (isfloat(condval) && fold_can_1(condval) && OPTS_OPTIMIZATION(OPTIM_CONST_FOLD_DCE)) { ast_expression_codegen *cgen; ir_block *elide; ir_value *dummy; bool istrue = (fold_immvalue_float(condval) != 0.0f && branch->on_true); bool isfalse = (fold_immvalue_float(condval) == 0.0f && branch->on_false); ast_expression *path = (istrue) ? branch->on_true : (isfalse) ? branch->on_false : NULL; if (!path) { /* * no path to take implies that the evaluation is if(0) and there * is no else block. so eliminate all the code. */ ++opts_optimizationcount[OPTIM_CONST_FOLD_DCE]; return true; } if (!(elide = ir_function_create_block(ast_ctx(branch), func->ir_func, ast_function_label(func, ((istrue) ? "ontrue" : "onfalse"))))) return false; if (!(*(cgen = path->codegen))((ast_expression*)path, func, false, &dummy)) return false; if (!ir_block_create_jump(func->curblock, ast_ctx(branch), elide)) return false; /* * now the branch has been eliminated and the correct block for the constant evaluation * is expanded into the current block for the function. */ func->curblock = elide; ++opts_optimizationcount[OPTIM_CONST_FOLD_DCE]; return true; } return -1; /* nothing done */ }
static int mp_add_to_form(const char *name, size_t nlen, const char *value, size_t len, const char *file, void *closure) { term_t head = PL_new_term_ref(); term_t tail = (term_t) closure; term_t val = PL_new_term_ref(); long vl; double vf; int rc; atom_t aname = 0; if ( isinteger(value, &vl, len) ) rc = PL_put_integer(val, vl); else if ( isfloat(value, &vf, len) ) rc = PL_put_float(val, vf); else rc = PL_unify_chars(val, PL_ATOM|REP_UTF8, len, value); rc = ( rc && PL_unify_list(tail, head, tail) && (aname = PL_new_atom_nchars(nlen, name)) && PL_unify_term(head, PL_FUNCTOR, PL_new_functor(aname, 1), PL_TERM, val) ); if ( aname ) PL_unregister_atom(aname); return rc; }
static GMQCC_INLINE ast_expression *fold_op_div(fold_t *fold, ast_value *a, ast_value *b) { if (isfloat(a)) { if (fold_can_2(a, b)) { return fold_constgen_float(fold, fold_immvalue_float(a) / fold_immvalue_float(b)); } else if (fold_can_1(b)) { return (ast_expression*)ast_binary_new( fold_ctx(fold), INSTR_MUL_F, (ast_expression*)a, fold_constgen_float(fold, 1.0f / fold_immvalue_float(b)) ); } } else if (isvector(a)) { if (fold_can_2(a, b)) { return fold_constgen_vector(fold, vec3_mulvf(fold_immvalue_vector(a), 1.0f / fold_immvalue_float(b))); } else { return (ast_expression*)ast_binary_new( fold_ctx(fold), INSTR_MUL_VF, (ast_expression*)a, (fold_can_1(b)) ? (ast_expression*)fold_constgen_float(fold, 1.0f / fold_immvalue_float(b)) : (ast_expression*)ast_binary_new( fold_ctx(fold), INSTR_DIV_F, (ast_expression*)fold->imm_float[1], (ast_expression*)b ) ); } } return NULL; }
void spn_value_print(const SpnValue *val) { switch (valtype(val)) { case SPN_TTAG_NIL: { fputs("nil", stdout); break; } case SPN_TTAG_BOOL: { fputs(boolvalue(val) ? "true" : "false", stdout); break; } case SPN_TTAG_NUMBER: { if (isfloat(val)) { printf("%.*g", DBL_DIG, floatvalue(val)); } else { printf("%ld", intvalue(val)); } break; } case SPN_TTAG_STRING: { SpnString *s = stringvalue(val); fputs(s->cstr, stdout); break; } case SPN_TTAG_ARRAY: { SpnArray *array = objvalue(val); print_array(array, 0); break; } case SPN_TTAG_HASHMAP: { SpnHashMap *hashmap = objvalue(val); print_hashmap(hashmap, 0); break; } case SPN_TTAG_FUNC: { SpnFunction *func = funcvalue(val); void *p; if (func->native) { p = (void *)(ptrdiff_t)(func->repr.fn); } else { p = func->repr.bc; } printf("<function %p>", p); break; } case SPN_TTAG_USERINFO: { void *ptr = isobject(val) ? objvalue(val) : ptrvalue(val); printf("<userinfo %p>", ptr); break; } default: SHANT_BE_REACHED(); break; } }
/* Return the difference of two expressions */ static exp_t * sub(exp_t *a1, exp_t *a2) { long n1, n2, d1, d2; exp_t *res; CHKNUM(a1, -); CHKNUM(a2, -); if (isfloat(a1) || isfloat(a2)) res = nfloat(VALUE(a1) - VALUE(a2)); else { n1 = NUMER(a1), n2 = NUMER(a2); d1 = DENOM(a1), d2 = DENOM(a2); res = nrat(n1*d2 - n2*d1, d1 * d2); } return res; }
static GMQCC_INLINE ast_expression *fold_op_sub(fold_t *fold, ast_value *a, ast_value *b) { if (isfloat(a)) { if (fold_can_2(a, b)) return fold_constgen_float(fold, fold_immvalue_float(a) - fold_immvalue_float(b)); } else if (isvector(a)) { if (fold_can_2(a, b)) return fold_constgen_vector(fold, vec3_sub(fold_immvalue_vector(a), fold_immvalue_vector(b))); } return NULL; }
static GMQCC_INLINE ast_expression *fold_op_neg(fold_t *fold, ast_value *a) { if (isfloat(a)) { if (fold_can_1(a)) return fold_constgen_float(fold, -fold_immvalue_float(a)); } else if (isvector(a)) { if (fold_can_1(a)) return fold_constgen_vector(fold, vec3_neg(fold_immvalue_vector(a))); } return NULL; }
unsigned long spn_hash_value(const SpnValue *key) { switch (valtype(key)) { case SPN_TTAG_NIL: { return 0; } case SPN_TTAG_BOOL: { return boolvalue(key); /* 0 or 1 */ } case SPN_TTAG_NUMBER: { if (isfloat(key)) { double f = floatvalue(key); /* only test for integer if it fits into one (anti-UB) */ if (LONG_MIN <= f && f <= LONG_MAX) { long i = f; /* truncate */ if (f == i) { /* it's really an integer. * This takes care of the +/- 0 problem too * (since 0 itself is an integer) */ return i; } } else { return spn_hash_bytes(&f, sizeof f); } } /* the hash value of an integer is itself */ return intvalue(key); } case SPN_TTAG_STRING: case SPN_TTAG_ARRAY: case SPN_TTAG_HASHMAP: case SPN_TTAG_FUNC: { SpnObject *obj = objvalue(key); unsigned long (*hashfn)(void *) = obj->isa->hashfn; return hashfn ? hashfn(obj) : (unsigned long)(obj); } case SPN_TTAG_USERINFO: { if (isobject(key)) { SpnObject *obj = objvalue(key); unsigned long (*hashfn)(void *) = obj->isa->hashfn; return hashfn ? hashfn(obj) : (unsigned long)(obj); } return (unsigned long)(ptrvalue(key)); } default: SHANT_BE_REACHED(); } return 0; }
static GMQCC_INLINE ast_expression *fold_op_xor(fold_t *fold, ast_value *a, ast_value *b) { if (isfloat(a)) { if (fold_can_2(a, b)) return fold_constgen_float(fold, (qcfloat_t)(((qcint_t)fold_immvalue_float(a)) ^ ((qcint_t)fold_immvalue_float(b)))); } else { if (fold_can_2(a, b)) { if (isvector(b)) return fold_constgen_vector(fold, vec3_xor(fold_immvalue_vector(a), fold_immvalue_vector(b))); else return fold_constgen_vector(fold, vec3_xorvf(fold_immvalue_vector(a), fold_immvalue_float(b))); } } return NULL; }
void Lexer::word() { _word[_wi++] = _stream->current(); while (!isBoundary(_stream->peek())) _word[_wi++] = _stream->read(); // does it look like a number? _word[_wi++] = '\0'; if (isint(_word)) add(new (collect) Term(TInt, atol(_word))); else if (isfloat(_word)) add(new (collect) Term(TDouble, atof(_word))); else add(new (collect) Term(TSymbol, Sym::lookup(_word))); _wi = 0; }
int load_config(const char *filepath) { SDL_RWops *fp = SDL_RWFromFile(filepath, "r"); if (!fp) { LOG_ERROR("Can't open file %s\n", filepath); return -1; } char buffer[256]; while (!rweof(fp)) { memset(buffer, 0, sizeof(buffer)); rwgets(buffer, sizeof(buffer), fp); if (buffer[0] == '#') continue; char *ptr; char *p = strtok_r(buffer, " \r\n", &ptr); if (p) { struct ConfigItem *item = malloc(sizeof(struct ConfigItem)); strncpy(item->key, p, MAX_CONFIGS_STR_KEY_SIZE); item->hash = pjw_hash(p); p = strtok_r(NULL, " \r\n", &ptr); if (isint(p)) { VARIANT_SET_INT(item->var, atoi(p)); } else if (isfloat(p)) { VARIANT_SET_FLOAT(item->var, atof(p)); } else { VARIANT_SET_STRING(item->var, p); } // TODO: check dublicate slist_append(configs, &item); } } SDL_RWclose(fp); return 0; }
static GMQCC_INLINE ast_expression *fold_op_not(fold_t *fold, ast_value *a) { if (isfloat(a)) { if (fold_can_1(a)) return fold_constgen_float(fold, !fold_immvalue_float(a)); } else if (isvector(a)) { if (fold_can_1(a)) return fold_constgen_float(fold, vec3_notf(fold_immvalue_vector(a))); } else if (isstring(a)) { if (fold_can_1(a)) { if (OPTS_FLAG(TRUE_EMPTY_STRINGS)) return fold_constgen_float(fold, !fold_immvalue_string(a)); else return fold_constgen_float(fold, !fold_immvalue_string(a) || !*fold_immvalue_string(a)); } } return NULL; }
unsigned long spn_hash_value(const SpnValue *key) { switch (valtype(key)) { case SPN_TTAG_NIL: { return 0; } case SPN_TTAG_BOOL: { return boolvalue(key); /* 0 or 1 */ } case SPN_TTAG_NUMBER: { if (isfloat(key)) { double f = floatvalue(key); long i = f; /* truncate */ if (f == i) { return i; /* it's really an integer */ } else { return spn_hash_bytes(&f, sizeof f); } } /* the hash value of an integer is itself */ return intvalue(key); } case SPN_TTAG_STRING: case SPN_TTAG_ARRAY: case SPN_TTAG_HASHMAP: case SPN_TTAG_FUNC: { SpnObject *obj = objvalue(key); unsigned long (*hashfn)(void *) = obj->isa->hashfn; return hashfn ? hashfn(obj) : (unsigned long)(obj); } case SPN_TTAG_USERINFO: { if (isobject(key)) { SpnObject *obj = objvalue(key); unsigned long (*hashfn)(void *) = obj->isa->hashfn; return hashfn ? hashfn(obj) : (unsigned long)(obj); } return (unsigned long)(ptrvalue(key)); } default: SHANT_BE_REACHED(); } return 0; }
static int checkfloat(int loc) { char *c; c = field[loc]; if (*c && (isfloat(*c))) { c++; while (*c) { if (!isfloatany(*c)) return 0; c++; } } else { return 0; } #ifdef DEBUG printf("%s is a float\n", field[loc]); #endif return 1; }
Tree calltree(Tree f, Type ty, Tree args, Symbol t3) { Tree p; if (args) f = tree(RIGHT, f->type, args, f); if (isstruct(ty)) assert(t3), p = tree(RIGHT, ty, tree(CALL+B, ty, f, addrof(idtree(t3))), idtree(t3)); else { Type rty = ty; if (isenum(ty)) rty = unqual(ty)->type; if (!isfloat(rty)) rty = promote(rty); p = tree(mkop(CALL, rty), rty, f, NULL); if (isptr(ty) || p->type->size > ty->size) p = cast(p, ty); } return p; }
static void push_arg(dbref player, struct frame *fr, const char *arg) { int num, lflag = 0; double nflt = 0.0; if (fr->argument.top >= STACK_SIZE) { anotify_nolisten(player, CFAIL "That would overflow the stack.", 1); return; } if (number(arg)) { /* push a number */ num = atoi(arg); push(fr->argument.st, &fr->argument.top, PROG_INTEGER, MIPSCAST &num); anotify_nolisten(player, CSUCC "Integer pushed.", 1); } else if (isfloat(arg)) { /* push a float */ nflt = atof(arg); push(fr->argument.st, &fr->argument.top, PROG_FLOAT, MIPSCAST &nflt); anotify_nolisten(player, CSUCC "Floating point number pushed.", 1); } else if (*arg == '#') { /* push a dbref */ if (!number(arg+1)) { anotify_nolisten(player, CINFO "I don't understand that dbref.", 1); return; } num = atoi(arg+1); push(fr->argument.st, &fr->argument.top, PROG_OBJECT, MIPSCAST &num); anotify_nolisten(player, CSUCC "Dbref pushed.", 1); } else if (*arg == 'L' || *arg == 'V' || *arg == 'l' || *arg == 'v') { if (*arg == 'L' || *arg == 'l') arg++, lflag = 1; if (*arg == 'V' || *arg == 'v') arg++; if (!number(arg)) { anotify_nolisten(player, CINFO "I don't understand which variable you mean.", 1); return; } num = atoi(arg); if (lflag) { push(fr->argument.st, &fr->argument.top, PROG_LVAR, MIPSCAST &num); anotify_nolisten(player, CSUCC "Local variable pushed.", 1); } else { push(fr->argument.st, &fr->argument.top, PROG_VAR, MIPSCAST &num); anotify_nolisten(player, CSUCC "Global variable pushed.", 1); } } else if (*arg == '"') { /* push a string */ char buf[BUFFER_LEN]; char *ptr; const char *ptr2; for (ptr = buf, ptr2 = arg+1; *ptr2; ptr2++) { if (*ptr2 == '\\') { if (!*(++ptr2)) break; *ptr++ = *ptr2; } else if (*ptr2 == '"') { break; } else { *ptr++ = *ptr2; } } *ptr = '\0'; push(fr->argument.st, &fr->argument.top, PROG_STRING, MIPSCAST alloc_prog_string(buf)); anotify_nolisten(player, CSUCC "String pushed.", 1); } else { anotify_nolisten(player, CINFO "I don't know that data type.", 1); } }
/* the actual string format parser * Although it's not in the documentation of `printf()`, but in addition to the * `%d` conversion specifier, this supports `%i`, which takes an `int` argument * instead of a `long`. It is used only for formatting error messages (since * Sparkling integers are all `long`s), but feel free to use it yourself. * * if `errmsg' is not a NULL pointer, and an error occurred while creating the * format string, then on return, `*errmsg' will point to a string containing * a message that describes the error. */ static char *make_format_string( const char *fmt, size_t *len, int argc, void *argv, int isval, char **errmsg ) { struct string_builder bld; int argidx = 0; const char *s = fmt; const char *p = s; /* points to the beginning of the next * non-format part of the format string */ init_builder(&bld); while (*s) { if (*s == '%') { struct format_args args; init_format_args(&args); /* append preceding non-format string chunk */ if (s > p) { append_string(&bld, p, s - p); } s++; /* Actually parse the format string. * '#' flag: prepend base prefix (0b, 0, 0x) */ if (*s == '#') { args.flags |= FLAG_BASEPREFIX; s++; } /* ' ' (space) flag: prepend space if non-negative * '+' flag: always prepend explicit + or - sign */ if (*s == ' ') { args.flags |= FLAG_PADSIGN; s++; } else if (*s == '+') { args.flags |= FLAG_EXPLICITSIGN; s++; } /* leading 0 flag: pad field with zeroes */ if (*s == '0') { args.flags |= FLAG_ZEROPAD; s++; } /* field width specifier */ if (isdigit(*s)) { args.width = 0; while (isdigit(*s)) { args.width *= 10; args.width += *s++ - '0'; } } else if (*s == '*') { s++; if (isval) { SpnValue *widthptr; /* check argc if the caller wants us to do so */ if (argc >= 0 && argidx >= argc) { format_errmsg(errmsg, OUT_OF_ARGUMENTS, argidx); free(bld.buf); return NULL; } /* width specifier must be an integer */ widthptr = getarg_val(argv, &argidx); if (!isnum(widthptr)) { format_errmsg( errmsg, TYPE_MISMATCH, argidx, SPN_TTAG_NUMBER, widthptr->type ); free(bld.buf); return NULL; } if (isfloat(widthptr)) { format_errmsg( errmsg, EXPECT_INTEGER, argidx ); free(bld.buf); return NULL; } args.width = intvalue(widthptr); } else { const int *widthptr = getarg_raw(argv, &argidx); args.width = *widthptr; } } /* precision/maximal length specifier */ if (*s == '.') { s++; if (*s == '+') { args.flags |= FLAG_EXPONENTSIGN; s++; } args.precision = 0; if (isdigit(*s)) { while (isdigit(*s)) { args.precision *= 10; args.precision += *s++ - '0'; } } else if (*s == '*') { s++; if (isval) { SpnValue *precptr; /* check argc if the caller wants us to do so */ if (argc >= 0 && argidx >= argc) { format_errmsg(errmsg, OUT_OF_ARGUMENTS, argidx); free(bld.buf); return NULL; } /* precision must be an integer too */ precptr = getarg_val(argv, &argidx); if (!isnum(precptr)) { format_errmsg( errmsg, TYPE_MISMATCH, argidx, SPN_TTAG_NUMBER, precptr->type ); free(bld.buf); return NULL; } if (isfloat(precptr)) { format_errmsg( errmsg, EXPECT_INTEGER, argidx ); free(bld.buf); return NULL; } args.precision = intvalue(precptr); } else { const int *precptr = getarg_raw(argv, &argidx); args.precision = *precptr; } } } args.spec = *s++; /* check argc if the caller wants us to do so */ if (argc >= 0 && argidx >= argc) { format_errmsg(errmsg, OUT_OF_ARGUMENTS, argidx); free(bld.buf); return NULL; } /* append parsed format string */ if (append_format(&bld, &args, argv, &argidx, isval, errmsg) != 0) { free(bld.buf); return NULL; } /* update non-format chunk base pointer */ p = s; } else { s++; } } /* if the format string doesn't end with a conversion specifier, * then just append the last non-format (literal) string chunk */ if (s > p) { append_string(&bld, p, s - p); } /* append terminating NUL byte */ expand_buffer(&bld, 1); bld.buf[bld.len] = 0; if (len != NULL) { *len = bld.len; } return bld.buf; }
/* returns zero on success, nonzero on error */ static int append_format( struct string_builder *bld, const struct format_args *args, void *argv, int *argidx, int isval, char **errmsg ) { switch (args->spec) { case '%': append_string(bld, "%", 1); break; case 's': { const char *str; size_t len; if (isval) { SpnString *strobj; /* must be a string */ SpnValue *val = getarg_val(argv, argidx); if (!isstring(val)) { format_errmsg( errmsg, TYPE_MISMATCH, *argidx, SPN_TYPE_STRING, val->type ); return -1; } strobj = stringvalue(val); str = strobj->cstr; len = strobj->len; } else { str = getarg_raw(argv, argidx); len = strlen(str); } if (args->precision >= 0 && args->precision < len) { len = args->precision; } if (args->width >= 0 && args->width > len) { size_t pad = args->width - len; expand_buffer(bld, pad); while (pad-- > 0) { bld->buf[bld->len++] = ' '; } } append_string(bld, str, len); break; } case 'i': case 'd': case 'b': case 'o': case 'u': case 'x': case 'X': { char *buf, *end, *begin; size_t len = PR_LONG_DIGITS; enum format_flags flags = args->flags; unsigned base = base_for_specifier(args->spec); long n; unsigned long u; if (isval) { /* must be a number */ SpnValue *val = getarg_val(argv, argidx); if (!isnum(val)) { format_errmsg( errmsg, TYPE_MISMATCH, *argidx, SPN_TTAG_NUMBER, val->type ); return -1; } if (isint(val)) { n = intvalue(val); } else { n = floatvalue(val); /* truncate */ } } else { /* "%i" expects an int, others expect a long */ if (args->spec == 'i') { n = *(const int *)getarg_raw(argv, argidx); } else { n = *(const long *)getarg_raw(argv, argidx); } } if (args->spec == 'i' || args->spec == 'd') { /* signed conversion specifiers */ if (n < 0) { flags |= FLAG_NEGATIVE; u = -n; } else { u = n; } } else { /* unsigned conversion specifiers */ u = n; } if (args->spec == 'X') { flags |= FLAG_CAPS; } if (args->width >= 0 && args->width > len) { len = args->width; } buf = spn_malloc(len); end = buf + len; begin = ulong2str(end, u, base, args->width, flags); assert(buf <= begin); append_string(bld, begin, end - begin); free(buf); break; } case 'c': { unsigned char ch; int len = 1; /* one character is one character long... */ if (isval) { /* must be an integer */ SpnValue *val = getarg_val(argv, argidx); if (!isnum(val)) { format_errmsg( errmsg, TYPE_MISMATCH, *argidx, SPN_TTAG_NUMBER, val->type ); return -1; } if (isfloat(val)) { format_errmsg(errmsg, EXPECT_INTEGER, *argidx); return -1; } ch = intvalue(val); } else { ch = *(const long *)getarg_raw(argv, argidx); } if (args->width > len) { len = args->width; } expand_buffer(bld, len); while (len-- > 1) { bld->buf[bld->len++] = ' '; } bld->buf[bld->len++] = ch; break; } case 'f': case 'F': { char *buf, *end, *begin; size_t len; int prec; double x; enum format_flags flags = args->flags; if (isval) { SpnValue *val = getarg_val(argv, argidx); if (!isnum(val)) { format_errmsg( errmsg, TYPE_MISMATCH, *argidx, SPN_TTAG_NUMBER, val->type ); return -1; } if (isfloat(val)) { x = floatvalue(val); } else { x = intvalue(val); } } else { x = *(const double *)getarg_raw(argv, argidx); } if (args->spec == 'F') { flags |= FLAG_CAPS; } /* handle special cases */ if (+1.0 / x == +1.0 / -0.0) { /* negative zero: set sign flag and carry on */ flags |= FLAG_NEGATIVE; } else if ( x != x /* NaN */ || x == +1.0 / 0.0 /* +inf */ || x == -1.0 / 0.0 /* -inf */ ) { print_special_fp(bld, flags, args->width, x); break; } if (x < 0.0) { flags |= FLAG_NEGATIVE; x = -x; } /* at this point, `x' is non-negative or -0 */ if (x >= 1.0) { len = ceil(log10(x)) + 1; /* 10 ^ n is n + 1 digits long */ } else { len = 1; /* leading zero needs exactly one character */ } prec = args->precision < 0 ? DBL_DIG : args->precision; len += prec + 3; /* decimal point, sign, leading zero */ if (args->width >= 0 && args->width > len) { len = args->width; } buf = spn_malloc(len); end = buf + len; begin = double2str(end, x, args->width, prec, flags); assert(buf <= begin); append_string(bld, begin, end - begin); free(buf); break; } case 'B': { int boolval; const char *str; size_t len; if (isval) { /* must be a boolean */ SpnValue *val = getarg_val(argv, argidx); if (!isbool(val)) { format_errmsg( errmsg, TYPE_MISMATCH, *argidx, SPN_TTAG_BOOL, val->type ); return -1; } boolval = boolvalue(val); } else { boolval = *(const int *)getarg_raw(argv, argidx); } str = boolval ? "true" : "false"; len = strlen(str); if (args->precision >= 0 && args->precision < len) { len = args->precision; } if (args->width >= 0 && args->width > len) { size_t pad = args->width - len; expand_buffer(bld, pad); while (pad-- > 0) { bld->buf[bld->len++] = ' '; } } append_string(bld, str, len); break; } default: format_errmsg(errmsg, INVALID_SPECIFIER, ++*argidx, args->spec); return -1; } return 0; }
int main(int argc, char *argv[]) { FILE *fp = stdin, *fpc; char *coef = NULL; double *x = NULL, *dx = NULL, **dw_coef = NULL, *y = NULL; int i, j, l, d, t, tj, ispipe, fsize, leng = LENG, total = T; int dw_num = 1, **dw_width = NULL, dw_calccoef = -1, dw_coeflen = 1, dw_leng = 1; char **dw_fn = (char **) calloc(sizeof(char *), argc); int non_magic_num, win_size_forward[2], win_size_backward[2]; float_list *top, *cur, *prev, *tmpf; if ((cmnd = strrchr(argv[0], '/')) == NULL) cmnd = argv[0]; else cmnd++; while (--argc) { if (**++argv == '-') { switch (*(*argv + 1)) { case 'd': if (dw_calccoef == 1 || dw_calccoef == 2) { fprintf(stderr, "%s : Options '-r' and '-d' should not be defined simultaneously!\n", cmnd); return (1); } dw_calccoef = 0; if (isfloat(*++argv)) { dw_coeflen = 0; for (i = 0; (i < argc - 1) && isfloat(argv[i]); i++) { dw_coeflen += strlen(argv[i]) + 1; } dw_coeflen += 1; coef = dw_fn[dw_num] = getmem(dw_coeflen, sizeof(char)); for (j = 0; j < i; j++) { sprintf(coef, " %s", *argv); coef += strlen(*argv) + 1; if (j < i - 1) { argv++; argc--; } } } else { dw_fn[dw_num] = *argv; } dw_num++; --argc; break; case 'r': if (dw_calccoef == 0 || dw_calccoef == 2) { fprintf(stderr, "%s : Options '-r' and '-d' should not be defined simultaneously!\n", cmnd); return (1); } dw_calccoef = 1; dw_coeflen = atoi(*++argv); --argc; if ((dw_coeflen != 1) && (dw_coeflen != 2)) { fprintf(stderr, "%s : Number of delta parameter should be 1 or 2!\n", cmnd); return (1); } if (argc <= 1) { fprintf(stderr, "%s : Window size for delta parameter required!\n", cmnd); return (1); } dw_fn[dw_num] = *++argv; dw_num++; --argc; if (dw_coeflen == 2) { if (argc <= 1) { fprintf(stderr, "%s : Window size for delta-delta parameter required!\n", cmnd); return (1); } dw_fn[dw_num] = *++argv; dw_num++; --argc; } break; case 'm': leng = atoi(*++argv) + 1; --argc; break; case 'l': leng = atoi(*++argv); --argc; break; case 'R': if (dw_calccoef == 0 || dw_calccoef == 1) { fprintf(stderr, "%s : Options '-r', '-d' and '-R' should not be defined simultaneously!\n", cmnd); return (1); } dw_calccoef = 2; dw_num = atoi(*++argv) + 1; --argc; if ((dw_num != 2) && (dw_num != 3)) { fprintf(stderr, "%s : Number of delta parameter should be 1 or 2!\n", cmnd); return (1); } if (argc <= 1) { fprintf(stderr, "%s : Window size for delta-delta parameter required!\n", cmnd); return (1); } sscanf(*++argv, "%d", &win_size_forward[0]); --argc; sscanf(*++argv, "%d", &win_size_backward[0]); --argc; if (dw_num > 2) { sscanf(*++argv, "%d", &win_size_forward[1]); --argc; sscanf(*++argv, "%d", &win_size_backward[1]); --argc; } break; case 'M': sscanf(*++argv, "%lf", &magic); MAGIC = TR; --argc; break; case 'h': usage(0); default: fprintf(stderr, "%s : Invalid option '%c'!\n", cmnd, *(*argv + 1)); usage(1); } } else fp = getfp(*argv, "rb"); } /* parse window files */ /* memory allocation */ if ((dw_width = (int **) calloc(dw_num, sizeof(int *))) == NULL) { fprintf(stderr, "%s : Cannot allocate memory!\n", cmnd); exit(1); } for (i = 0; i < dw_num; i++) if ((dw_width[i] = (int *) calloc(2, sizeof(int))) == NULL) { fprintf(stderr, "%s : Cannot allocate memory!\n", cmnd); exit(1); } if ((dw_coef = (double **) calloc(dw_num, sizeof(double *))) == NULL) { fprintf(stderr, "%s : Cannot allocate memory!\n", cmnd); exit(1); } /* window for static parameter */ dw_width[0][0] = dw_width[0][1] = 0; dw_coef[0] = dgetmem(1); dw_coef[0][0] = 1; /* set delta coefficients */ if (dw_calccoef == 0) { for (i = 1; i < dw_num; i++) { if (dw_fn[i][0] == ' ') { fsize = str2darray(dw_fn[i], &(dw_coef[i])); } else { /* read from file */ fpc = getfp(dw_fn[i], "rb"); /* check the number of coefficients */ fseek(fpc, 0L, 2); fsize = ftell(fpc) / sizeof(real); fseek(fpc, 0L, 0); /* read coefficients */ dw_coef[i] = dgetmem(fsize); freadf(dw_coef[i], sizeof(**(dw_coef)), fsize, fpc); } /* set pointer */ dw_leng = fsize / 2; dw_coef[i] += dw_leng; dw_width[i][0] = -dw_leng; dw_width[i][1] = dw_leng; if (fsize % 2 == 0) dw_width[i][1]--; } } else if (dw_calccoef == 1) { int a0, a1, a2; for (i = 1; i < dw_num; i++) { dw_leng = atoi(dw_fn[i]); if (dw_leng < 1) { fprintf(stderr, "%s : Width for regression coefficient shuould be more than 1!\n", cmnd); exit(1); } dw_width[i][0] = -dw_leng; dw_width[i][1] = dw_leng; dw_coef[i] = dgetmem(dw_leng * 2 + 1); dw_coef[i] += dw_leng; } dw_leng = atoi(dw_fn[1]); for (a1 = 0, j = -dw_leng; j <= dw_leng; a1 += j * j, j++); for (j = -dw_leng; j <= dw_leng; j++) dw_coef[1][j] = (double) j / (double) a1; if (dw_num > 2) { dw_leng = atoi(dw_fn[2]); for (a0 = a1 = a2 = 0, j = -dw_leng; j <= dw_leng; a0++, a1 += j * j, a2 += j * j * j * j, j++); for (j = -dw_leng; j <= dw_leng; j++) dw_coef[2][j] = 2 * ((double) (a0 * j * j - a1)) / ((double) (a2 * a0 - a1 * a1)); } } /* -- Count number of input vectors and read -- */ x = dgetmem(leng); top = prev = (float_list *) malloc(sizeof(float_list)); top->f = (float *) malloc(sizeof(float) * leng); total = 0; prev->next = NULL; while (freadf(x, sizeof(*x), leng, fp) == leng) { cur = (float_list *) malloc(sizeof(float_list)); cur->f = (float *) malloc(sizeof(float) * leng); for (i = 0; i < leng; i++) { cur->f[i] = (float) x[i]; } total++; prev->next = cur; cur->next = NULL; prev = cur; } free(x); x = dgetmem(leng * total); dx = dgetmem(dw_num * leng * total); fillz(dx, sizeof(*x), dw_num * leng * total); for (i = 0, tmpf = top->next; tmpf != NULL; i++, tmpf = tmpf->next) { for (j = 0; j < leng; j++) { x[i * leng + j] = tmpf->f[j]; } } if (dw_calccoef == 0 || dw_calccoef == 1) { /* calculate delta and delta-delta */ for (t = 0; t < total; t++) { for (d = 0; d < dw_num; d++) { for (j = dw_width[d][0]; j <= dw_width[d][1]; j++) { tj = t + j; if (tj < 0) tj = 0; if (!(tj < total)) tj = total - 1; for (l = 0; l < leng; l++) dx[dw_num * leng * t + leng * d + l] += dw_coef[d][j] * x[leng * tj + l]; } } } /* output static, delta, delta-delta */ fwritef(dx, sizeof(*dx), dw_num * total * leng, stdout); } else if (dw_calccoef == 2) { int *position = (int *) malloc(sizeof(int) * total); /* skip magic number */ if (MAGIC == TR) { for (t = 0, non_magic_num = 0; t < total; t++) { for (l = 0; l < leng; l++) { if (x[leng * t + l] == magic) { break; } } if (l == leng) { /* remember position of non-magic number */ position[non_magic_num] = t; non_magic_num++; } } } else { for (t = 0; t < total; t++) { position[t] = t; } non_magic_num = total; } /* calculate delta and delta-delta */ GetCoefficient(x, dx, dw_num, position, total, non_magic_num, leng, win_size_forward, win_size_backward); /* output static, delta, delta-delta */ fwritef(dx, sizeof(*dx), dw_num * total * leng, stdout); } return (0); }
double StringValue::Double() const { if(!isfloat(m_val.c_str())) return 0; return atof(m_val.c_str()); }
float StringValue::Float() const { if(!isfloat(m_val.c_str())) return 0.0f; return (float)atof(m_val.c_str()); }
BOOLEAN isarithmetic(TYPE *tp) { tp = basetype(tp); return isint(tp) || isfloat(tp) || iscomplex(tp) || isimaginary(tp); }
int main(int argc, char **argv) { FILE *pdffp = stdin, *parfp = stdout; int nframe, delay; char *coef; int coeflen; PStream pst; int i, j; void InitPStream(PStream *); double *mlpg(PStream *); pst.order = ORDER; pst.range = RANGE; pst.iType = ITYPE; pst.dw.fn = (char **) calloc(sizeof(char *), argc); pst.dw.num = 1; pst.dw.calccoef = -1; if ((cmnd = strrchr(argv[0], '/')) == NULL) cmnd = argv[0]; else cmnd++; while (--argc) { if (**++argv == '-') { switch (*(*argv + 1)) { case 'd': if (pst.dw.calccoef == 1) { fprintf(stderr, "%s : Options '-r' and '-d' should not be defined simultaneously!\n", cmnd); return (1); } pst.dw.calccoef = 0; if (isfloat(*++argv)) { coeflen = 0; for (i = 0; (i < argc - 1) && isfloat(argv[i]); i++) { coeflen += strlen(argv[i]) + 1; } coeflen += 1; coef = pst.dw.fn[pst.dw.num] = getmem(coeflen, sizeof(char)); for (j = 0; j < i; j++) { sprintf(coef, " %s", *argv); coef += strlen(*argv) + 1; if (j < i - 1) { argv++; argc--; } } } else { pst.dw.fn[pst.dw.num] = *argv; } pst.dw.num++; --argc; break; case 'r': if (pst.dw.calccoef == 0) { fprintf(stderr, "%s : Options '-r' and '-d' should not be defined simultaneously!\n", cmnd); return (1); } pst.dw.calccoef = 1; coeflen = atoi(*++argv); --argc; if ((coeflen != 1) && (coeflen != 2)) { fprintf(stderr, "%s : Number of delta parameter should be 1 or 2!\n", cmnd); return (1); } if (argc <= 1) { fprintf(stderr, "%s : Window size for delta parameter required!\n", cmnd); return (1); } pst.dw.fn[pst.dw.num] = *++argv; pst.dw.num++; --argc; if (coeflen == 2) { if (argc <= 1) { fprintf(stderr, "%s : Window size for delta-delta parameter required!\n", cmnd); return (1); } pst.dw.fn[pst.dw.num] = *++argv; pst.dw.num++; --argc; } break; case 'm': pst.order = atoi(*++argv); --argc; break; case 'l': pst.order = atoi(*++argv) - 1; --argc; break; case 'i': pst.iType = atoi(*++argv); --argc; break; case 's': pst.range = atoi(*++argv); --argc; break; case 'h': usage(0); default: fprintf(stderr, "%s : Invalid option '%c'!\n", cmnd, *(*argv + 1)); usage(1); } } else pdffp = getfp(*argv, "rb"); } InitPStream(&pst); delay = pst.range + pst.dw.maxw[WRIGHT]; nframe = 0; while (freadf(pst.mean, sizeof(*(pst.mean)), pst.vSize * 2, pdffp) == pst.vSize * 2) { if (pst.dw.num == 1) fwritef(pst.mean, sizeof(*pst.mean), pst.order + 1, parfp); else { if (pst.iType == 0) for (i = 0; i < pst.vSize; i++) pst.ivar[i] = finv(pst.ivar[i]); mlpg(&pst); if (nframe >= delay) fwritef(pst.par, sizeof(*(pst.par)), pst.order + 1, parfp); } nframe++; } if (pst.dw.num > 1) { for (i = 0; i < pst.vSize; i++) { pst.mean[i] = 0.0; pst.ivar[i] = 0.0; } for (i = 0; i < min(nframe, delay); i++) { mlpg(&pst); fwritef(pst.par, sizeof(*(pst.par)), pst.order + 1, parfp); } } return (0); }