static void knh_stack_writeStackTrace(Ctx *ctx, knh_sfp_t *sfp, knh_OutputStream_t *w) { knh_Method_t *mtd = sfp[K_MTDIDX].callmtd; knh_write_sname(ctx, w, DP(mtd)->cid); if(DP(mtd)->mn != MN_LAMBDA) { int i = 0, psize = knh_Method_psize(mtd); knh_putc(ctx, w, '.'); knh_write_mn(ctx, w, DP(mtd)->mn); knh_putc(ctx, w, '('); for(i = 0; i < psize; i++) { knh_param_t *p = knh_ParamArray_get(DP(mtd)->mp, i); knh_type_t type = knh_type_tocid(ctx, p->type, knh_Object_cid(sfp[0].o)); if(i > 0) { knh_putc(ctx, w, ','); } knh_write_fn(ctx, w, p->fn); knh_putc(ctx, w, '='); if(!knh_write_ndata(ctx, w, type, sfp[i+1].data)) { knh_Method_t *mtdf = knh_getSystemFormatter(ctx, type, MN__k); knh_write_Object(ctx, w, ctx->esp, &mtdf, sfp[i+1].o); } } knh_putc(ctx, w, ')'); } }
static METHOD knh__HashMap_get(Ctx *ctx, knh_sfp_t *sfp) { HashMap *o = (HashMap*)sfp[0].o; knh_hcode_t hcode = knh_stack_hashCode(ctx, sfp + 1); knh_uintptr_t h = hcode % DP(o)->hmax; knh_hashentry_t *e = DP(o)->array[h]; while(e != NULL) { if(e->hcode == hcode && knh_Object_cid(sfp[1].o) == knh_Object_cid(e->key) && knh_stack_equals(ctx, sfp + 1, e->key)) { KNH_RETURN(ctx, sfp, e->value); } e = e->next; } KNH_RETURN(ctx, sfp, KNH_NULL); }
METHOD Chardev_new(Ctx *ctx, knh_sfp_t *sfp) { printk("%s:%d\n",__func__,__LINE__); knh_device_t *dev = new_device(ctx, sfp[1].s); knh_RawPtr_init(ctx, sfp[0].glue, dev, device_gfree); // set ref for object. // but we do not set ref because it becomes cyclic refalence. dev->self = sfp[0].o; printk("%s:%d, cid=%d\n",__func__,__LINE__, knh_Object_cid(sfp[0].o)); KNH_RETURN(ctx, sfp, sfp[0].o); }
void knh_write_Object(Ctx *ctx, knh_OutputStream_t *w, knh_sfp_t *esp, knh_Method_t **mtdP, knh_Object_t *o) { knh_class_t cid = knh_Object_cid(o); knh_Method_t *mtd = mtdP[0]; if(!knh_Method_isPoly(mtd, cid)) { mtd = knh_getSystemFormatter(ctx, cid, DP(mtd)->mn); mtdP[0] = mtd; } KNH_SETv(ctx, esp[K_CALLDELTA].o, w); KNH_SETv(ctx, esp[K_CALLDELTA+1].o, o); esp[K_CALLDELTA+1].data = knh_Object_data(o); // this is necessary KNH_SCALL(ctx, esp, 0, mtd, 1); }
//## method @Virtual void Chardev.read(File! file, OutputStream ous); static ssize_t script_read (struct file* filp, char __user *user_buf, size_t count, loff_t *offset) { printk("%s at %d\n",__func__,__LINE__); knh_device_t *dev = filp->private_data; knh_Object_t *self = dev->self; if(*offset > 0) return 0; Ctx *ctx = knh_getCurrentContext(); knh_sfp_t *sfp = KNH_LOCAL(ctx); knh_Method_t *mtd = dev->read; if (!IS_Method(mtd) || knh_Method_isAbstract(mtd)) { knh_bytes_t fname = B("read"); knh_methodn_t mn = knh_getmn(ctx, fname, METHODN_NONAME); mtd = knh_Class_getMethod(ctx, knh_Object_cid(self), mn); KNH_SETv(ctx, dev->read, mtd); } //knh_File_t *f = (knh_File_t*)new_Object_bcid(ctx, CLASS_File, 0); //f->file = filp; if (IS_Method(mtd)) { KNH_MOV(ctx, sfp[0].o, new_ExceptionHandler(ctx)); KNH_TRY(ctx, L_CATCH, sfp, 0); { knh_cwb_t cwbbuf, *cwb = knh_cwb_open(ctx, &cwbbuf); // THIS IS DANGEROUS. DON'T USED by KIMIO // knh_OutputStream_t *o = new_BytesOutputStream(ctx, cwb->ba); // KNH_MOV(ctx, sfp[1].o, self); // //KNH_MOV(ctx, sfp[2].o, f); // KNH_MOV(ctx, sfp[2].o, KNH_NULL); // KNH_MOV(ctx, sfp[3].o, o); // KNH_SCALL(ctx, sfp, 0, mtd, 2); // { // size_t len = knh_cwb_size(cwb); // char *buf = knh_cwb_tochar(ctx, cwb); // if(copy_to_user(user_buf,buf,len)){ // printk(KERN_ALERT "%s: copy_to_user failed\n",__func__); // return -EFAULT; // } // knh_cwb_close(cwb); // knh_Context_clearstack(ctx); // *offset += len; // return len; // } } /* catch */ L_CATCH:; KNH_PRINT_STACKTRACE(ctx, sfp, 0); } return 0; }
static METHOD knh__HashMap_set(Ctx *ctx, knh_sfp_t *sfp) { if(IS_IMM(sfp[0].o)) { if(IS_NULL(sfp[2].o)) { knh__HashMap_remove(ctx, sfp); return ; } knh_Hash_t *o = (knh_Hash_t*)sfp[0].o; knh_hcode_t hcode = knh_stack_hashCode(ctx, sfp + 1); knh_uintptr_t h = hcode % DP(o)->hmax; knh_hashentry_t *e = DP(o)->array[h]; while(e != NULL) { if(e->hcode == hcode && knh_Object_cid(sfp[1].o) == knh_Object_cid(e->key) && knh_stack_equals(ctx, sfp + 1, e->key)) { knh_sfp_boxing(ctx, sfp+2); KNH_SETv(ctx, e->value, sfp[2].o); KNH_RETURN_void(ctx, sfp); } e = e->next; } /* add newentry */ { e = new_hashentry(ctx, o); e->hcode = hcode; knh_sfp_boxing(ctx, sfp+1); KNH_INITv(e->key, sfp[1].o); knh_sfp_boxing(ctx, sfp+2); KNH_INITv(e->value, sfp[2].o); e->next = DP(o)->array[h]; DP(o)->array[h] = e; DP(o)->size++; } } KNH_RETURN_void(ctx, sfp); }
static METHOD knh__HashMap_remove(Ctx *ctx, knh_sfp_t *sfp) { if(IS_IMM(sfp[0].o)) { knh_Hash_t *o = (knh_Hash_t*)sfp[0].o; knh_hcode_t hcode = knh_stack_hashCode(ctx, sfp + 1); knh_uintptr_t h = hcode % DP(o)->hmax; knh_hashentry_t *e = DP(o)->array[h]; knh_hashentry_t **prev_next = &(DP(o)->array[h]); while(e != NULL) { if(e->hcode == hcode && knh_Object_cid(sfp[1].o) == knh_Object_cid(e->key) && knh_stack_equals(ctx, sfp + 1, e->key)) { prev_next[0] = e->next; knh_hashentry_collect(ctx, o, e); DP(o)->size--; } prev_next = &(e->next); e = e->next; } } KNH_RETURN_void(ctx, sfp); }
static METHOD knh__String_format(Ctx *ctx, knh_sfp_t *sfp) { knh_bytes_t fmt = knh_String_tobytes(sfp[0].s); knh_sfp_t *param = sfp + 1; int ac = knh_stack_argc(ctx, param); knh_bytes_t mt, expr, next; if(!knh_bytes_findMT(ctx, fmt, &mt, &expr, &next)) { KNH_RETURN(ctx, sfp, sfp[0].s); } knh_cwb_t cwbbuf, *cwb = knh_cwb_open(ctx, &cwbbuf); int count; for(count = 0; ; count++) { if(mt.buf > fmt.buf + 1) { fmt.len = (mt.buf - fmt.buf) - 1; knh_Bytes_write(ctx, cwb->ba, fmt); } int index = count; if(expr.len > 0) { knh_int_t num; if(knh_bytes_parseint(expr, &num)) { index = (int)num; } } if(0 <= index && index < ac) { knh_sfp_t *esp = KNH_LOCAL(ctx); KNH_SETv(ctx, esp[1].o, param[index].o); esp[1].data = param[index].data; Object *m = KNH_NULL; if(knh_bytes_isOptionalMT(mt)) m = UP(new_String(ctx, mt, NULL)); mt.buf = mt.buf - 1; mt.len++; /* 's' == > '%s' */ knh_methodn_t mn = knh_getmn(ctx, mt, METHODN__empty); knh_esp1_format(ctx, mn, cwb->w, m); } else { if(knh_Context_isDebug(ctx)) { KNH_THROW_OUTOFINDEX(ctx, index, ac); } } fmt.buf = next.buf; fmt.len = next.len; if(!knh_bytes_findMT(ctx, fmt, &mt, &expr, &next)) { break; } } if(fmt.len > 0) { knh_Bytes_write(ctx, cwb->ba, fmt); } KNH_RETURN(ctx, sfp, new_StringX__cwb(ctx, knh_Object_cid(sfp[0].o), cwb)); }
static void knh_String__k(Ctx *ctx, String *o, OutputStream *w, String *m) { int quote = '\''; if(knh_Object_cid(o) == CLASS_String) quote = '"'; knh_putc(ctx, w, quote); knh_bytes_t t = knh_String_tobytes(o); knh_bytes_t sub = t; size_t i, s = 0; for(i = 0; i < o->size; i++) { switch(t.buf[i]) { case '\t' : sub.buf = t.buf + s; sub.len = i - s; knh_print(ctx, w, sub); s = i + 1; knh_putc(ctx, w, '\\'); knh_putc(ctx, w, 't'); break ; case '\n' : sub.buf = t.buf + s; sub.len = i - s; knh_print(ctx, w, sub); s = i + 1; knh_putc(ctx, w, '\\'); knh_putc(ctx, w, 'n'); break ; case '\r' : sub.buf = t.buf + s; sub.len = i - s; knh_print(ctx, w, sub); s = i + 1; knh_putc(ctx, w, '\\'); knh_putc(ctx, w, 'r'); break ; case '\\' : sub.buf = t.buf + s; sub.len = i - s; knh_print(ctx, w, sub); s = i + 1; knh_putc(ctx, w, '\\'); knh_putc(ctx, w, '\\'); break ; default: if(t.buf[i] == quote) { sub.buf = t.buf + s; sub.len = i - s; knh_print(ctx, w, sub); s = i + 1; knh_putc(ctx, w, '\\'); knh_putc(ctx, w, quote); } } } if (s < t.len) { sub.buf = t.buf + s; sub.len = t.len - s; knh_print(ctx, w, sub); } knh_putc(ctx, w, quote); }
void knh_throw(Ctx *ctx, knh_sfp_t *sfp, long start) { if(IS_Exception(ctx->e)) { knh_sfp_t *sp = (sfp == NULL) ? ctx->esp : sfp + start; while(ctx->stack <= sp) { DBG_P("[%d] cid=%s ivalue=%lld", (sp - ctx->stack), CLASS__(knh_Object_cid(sp[0].o)), sp[0].ivalue); if(sp[0].callmtd != NULL && isCalledMethod(ctx, sp)) { sp = knh_Exception_addStackTrace(ctx, ctx->e, sp+1); } if(IS_ExceptionHandler(sp[0].hdr) && DP(sp[0].hdr)->return_address != NULL) { knh_ExceptionHandler_longjmp(ctx, sp[0].hdr); goto L_NOCATCH; } sp--; } L_NOCATCH:; { knh_Method_t *mtdf = knh_getSystemFormatter(ctx, CLASS_Exception, MN__dump); knh_write_Object(ctx, KNH_STDERR, sfp, &mtdf, UPCAST(ctx->e)); } knh_exit(ctx, 0); } }
void knh_vprintf(Ctx *ctx, knh_OutputStream_t *w, const char *fmt, va_list ap) { knh_valist_t args[10]; const char *c = fmt; int i, ch, bindex = 0, bindex_max = 10; for(i = 0; i < bindex_max; i++) args[i].atype = 0; while((ch = *c) != '\0') { c++; if(ch == '%') { int index; ch = *c; if(ch == '%') { c++; continue; } index = bindex++; c = knh_vprintf_parseindex(c++, &index); //DBG_P("bindex=%d, index=%d", bindex, index); switch(ch) { case 'd': case 'u': args[index].atype = VA_DIGIT; break; case 'l': case 'i': args[index].atype = VA_LONG; break; case 'f': case 'e': args[index].atype = VA_FLOAT; break; case 's': args[index].atype = VA_CHAR; break; case 'p': args[index].atype = VA_POINTER; break; case 'L': case 'K': case 'k': case 'O': case 'o': args[index].atype = VA_OBJECT; break; case 'N': case 'F': args[index].atype = VA_FIELDN; break; case 'M': args[index].atype = VA_METHODN; break; case 'C': args[index].atype = VA_CLASS; break; case 'T': args[index].atype = VA_TYPE; break; case 'B': args[index].atype = VA_BYTES; break; // TODO // we should care if "fmt" has "%%". // sometimes, next args is NULL. case '%': index--; c++; default: bindex--; } if(bindex == 10) { DBG_ASSERT(bindex < 10); break; } } } for(i = 0; i < 10; i++) { switch(args[i].atype) { case VA_DIGIT: args[i].dvalue = (knh_intptr_t)va_arg(ap, knh_intptr_t); break; case VA_LONG: args[i].ivalue = (knh_int_t)va_arg(ap, knh_int_t); break; case VA_FLOAT: #if defined(K_USING_NOFLOAT) args[i].fvalue = (knh_float_t)va_arg(ap, knh_float_t); #else args[i].fvalue = (knh_float_t)va_arg(ap, double); #endif break; case VA_CHAR: args[i].svalue = (char*)va_arg(ap, char*); break; case VA_POINTER: args[i].pvalue = (void*)va_arg(ap, void*); break; case VA_OBJECT: args[i].ovalue = (Object*)va_arg(ap, Object*); break; case VA_FIELDN: args[i].fn = (knh_fieldn_t)va_arg(ap, int/*knh_fieldn_t*/); break; case VA_METHODN: args[i].mn = (knh_methodn_t)va_arg(ap, int/*knh_methodn_t*/); break; case VA_CLASS: args[i].cid = (knh_class_t)va_arg(ap, int/*knh_class_t*/); break; case VA_TYPE: args[i].type = (knh_type_t)va_arg(ap, int/*knh_type_t*/); break; case VA_BYTES: args[i].bvalue = (knh_bytes_t)va_arg(ap, knh_bytes_t); break; default: bindex_max = i; goto L_FORMAT; } } L_FORMAT: { knh_bytes_t b; knh_Method_t *mtd = NULL; knh_sfp_t *esp = ctx->esp; c = fmt; bindex = 0; b.text = c; b.len = 0; while((ch = *c) != '\0') { c++; if(ch == '\\') { if(b.len > 0) { knh_print(ctx, w, b); } ch = *c; switch(ch) { case '\0' : return ; case 'n': knh_println(ctx, w, STEXT("")); break; case 't': knh_write_TAB(ctx, w); break; default: knh_putc(ctx, w, '\\'); knh_putc(ctx, w, ch); } b.text = c; b.len = 0; } else if(ch == '%') { if(b.len > 0) { knh_print(ctx, w, b); } ch = *c; if(ch == '%') { knh_putc(ctx, w, '%'); c++; b.text = c; b.len = 0; continue; } int index = bindex++; c = knh_vprintf_parseindex(++c, &index); switch(ch) { case '\0' : return ; case 'd': DBG_ASSERT(args[index].atype == VA_DIGIT); knh_write_dfmt(ctx, w, K_INTPTR_FMT, args[index].dvalue); break; case 'u': DBG_ASSERT(args[index].atype == VA_DIGIT); knh_write_dfmt(ctx, w, K_INTPTR_UFMT, args[index].uvalue); break; case 'l': case 'i' : DBG_ASSERT(args[index].atype == VA_LONG); knh_write_ifmt(ctx, w, K_INT_FMT, args[index].ivalue); break; case 'f': DBG_ASSERT(args[index].atype == VA_FLOAT); knh_write_ffmt(ctx, w, K_FLOAT_FMT, args[index].fvalue); break; case 'e': DBG_ASSERT(args[index].atype == VA_FLOAT); knh_write_ffmt(ctx, w, K_FLOAT_FMTE, args[index].fvalue); break; case 's': DBG_ASSERT(args[index].atype == VA_CHAR); knh_write(ctx, w, B(args[index].svalue)); break; case 'p': DBG_ASSERT(args[index].atype == VA_POINTER); knh_write__p(ctx, w, args[index].pvalue); break; case 'L': DBG_ASSERT(args[index].atype == VA_OBJECT); if(IS_Token(args[index].ovalue)) { knh_write_token(ctx, w, (knh_Token_t*)args[index].ovalue); break; } case 'O': case 'o': DBG_ASSERT(args[index].atype == VA_OBJECT); mtd = knh_getSystemFormatter(ctx, knh_Object_cid(args[index].ovalue), MN__s); knh_write_Object(ctx, w, esp, &mtd, args[index].ovalue); break; case 'K': case 'k': DBG_ASSERT(args[index].atype == VA_OBJECT); mtd = knh_getSystemFormatter(ctx, knh_Object_cid(args[index].ovalue), MN__k); knh_write_Object(ctx, w, esp, &mtd, args[index].ovalue); break; case 'N': case 'F': DBG_ASSERT(args[index].atype == VA_FIELDN); knh_write_text(ctx, w, FN__(args[index].fn)); break; case 'M': DBG_ASSERT(args[index].atype == VA_METHODN); knh_write_mn(ctx, w, args[index].mn); break; case 'C': DBG_ASSERT(args[index].atype == VA_CLASS); knh_write_sname(ctx, w, args[index].cid); break; case 'T': DBG_ASSERT(args[index].atype == VA_TYPE); knh_write_type(ctx, w, args[index].type); break; case 'B': DBG_ASSERT(args[index].atype == VA_BYTES); knh_write(ctx,w, args[index].bvalue); break; case '%': index--; bindex--; default: //knh_putc(ctx, w, '%'); knh_putc(ctx, w, ch); } b.text = c; b.len = 0; if(!(bindex <= bindex_max)) { DBG_ASSERT(bindex <= bindex_max); break; } } else { b.len = b.len+1; } } if(b.len > 0) { knh_print(ctx, w, b); } } }