static bool String_equal(KonohaContext *kctx, kString *str0, kString *str1) { if(kString_size(str0) == kString_size(str1)) { return strncmp(kString_text(str0), kString_text(str1), kString_size(str0)) == 0; } return false; }
void test_kString(KonohaContext *kctx) { intptr_t i; kString *s; for (i = 0; i < 100; ++i) { s = KLIB new_kString(kctx, GcUnsafe, "abcd", 4, 0); assert(strcmp(kString_text(s), "abcd") == 0); assert(kString_size(s) == 4); assert(kString_Is(ASCII, s) == 1); } for (i = 0; i < 100; ++i) { s = KLIB new_kString(kctx, GcUnsafe, "abcd", 4, 0); assert(strcmp(kString_text(s), "abcd") == 0); assert(kString_size(s) == 4); assert(kString_text(s) == (char*)s->inline_text); } for (i = 0; i < 100; ++i) { static const char *text = "12345678901234567890"; s = KLIB new_kString(kctx, GcUnsafe, text, 20, StringPolicy_TEXT | StringPolicy_UTF8); assert(strcmp(kString_text(s), text) == 0); assert(kString_size(s) == 20); assert(kString_text(s) == text); assert(kString_Is(ASCII, s) == 0); } }
//## void File.print(String line); static KMETHOD File_print(KonohaContext *kctx, KonohaStack *sfp) { kFile *file = sfp[0].asFile; kString *line = sfp[1].asString; KMakeTrace(trace, sfp); if(file->writerIconv == ICONV_NULL || kString_Is(ASCII, line)) { TRACE_fwrite(kctx, file, kString_text(line), kString_size(line), trace); } else { KBuffer wb; KLIB KBuffer_Init(&(kctx->stack->cwb), &wb); KLIB KBuffer_iconv(kctx, &wb, file->writerIconv, kString_text(line), kString_size(line), trace); TRACE_fwrite(kctx, file, KLIB KBuffer_text(kctx, &wb, NonZero), KBuffer_bytesize(&wb), trace); KLIB KBuffer_Free(&wb); } }
//## boolean NameSpace.DefineMacro(String symbol, int param, String source); static KMETHOD NameSpace_DefineMacro(KonohaContext *kctx, KonohaStack *sfp) { ksymbol_t keyword = KAsciiSymbol(kString_text(sfp[1].asString), kString_size(sfp[1].asString), _NEWID); int paramsize = (int)sfp[2].intValue; kString *source = sfp[3].asString; KReturnUnboxValue(SUGAR SetMacroData(kctx, sfp[0].asNameSpace, keyword, paramsize, kString_text(source), true)); }
// boolean NameSpace.hate(String symbol); static KMETHOD NameSpace_hate(KonohaContext *kctx, KonohaStack *sfp) { kString *key = sfp[2].asString; ksymbol_t keyword = KAsciiSymbol(kString_text(key), kString_size(key), _NEWID); KMakeTrace(trace, sfp); kNameSpace_RemoveSyntax(kctx, sfp[0].asNameSpace, keyword, trace); }
//## String DIR.readPath() static KMETHOD DIR_readPath(KonohaContext *kctx, KonohaStack *sfp) { kDir *dir = (kDir *)sfp[0].asObject; if(dir->dirp != NULL) { KMakeTrace(trace, sfp); struct dirent entry, *result; int ret = readdir_r(dir->dirp, &entry, &result); if(result != NULL) { char *d_name = result->d_name, delim[2] = {'/', 0}; KBuffer wb; KLIB KBuffer_Init(&(kctx->stack->cwb), &wb); KLIB KBuffer_Write(kctx, &wb, kString_text(dir->PathInfoNULL), kString_size(dir->PathInfoNULL)); KLIB KBuffer_Write(kctx, &wb, delim, 1); if(dir->readerIconv != ICONV_NULL) { KLIB KBuffer_Write(kctx, &wb, d_name, strlen(d_name)); } else { KLIB KBuffer_iconv(kctx, &wb, dir->readerIconv, d_name, strlen(d_name), trace); } KReturn(KLIB KBuffer_Stringfy(kctx, &wb, OnStack, StringPolicy_FreeKBuffer)); } if(ret == -1) { KTraceErrorPoint(trace, SystemFault, "readdir", LogErrno); } kDir_close(kctx, dir); } KReturn(KNULL(String)); }
/* copied from src/sugar/sugarfunc.h */ static kString *kToken_ResolveEscapeSequence(KonohaContext *kctx, kToken *tk, size_t start) { KBuffer wb; KLIB KBuffer_Init(&(kctx->stack->cwb), &wb); const char *text = kString_text(tk->text) + start; const char *end = kString_text(tk->text) + kString_size(tk->text); KLIB KBuffer_Write(kctx, &wb, kString_text(tk->text), start); while(text < end) { int ch = *text; if(ch == '\\' && *(text+1) != '\0') { switch (*(text+1)) { /* * compatible with ECMA-262 * http://ecma-international.org/ecma-262/5.1/#sec-7.8.4 */ case 'b': ch = '\b'; text++; break; case 't': ch = '\t'; text++; break; case 'n': ch = '\n'; text++; break; case 'v': ch = '\v'; text++; break; case 'f': ch = '\f'; text++; break; case 'r': ch = '\r'; text++; break; case '"': ch = '"'; text++; break; case '\'': ch = '\''; text++; break; case '\\': ch = '\\'; text++; break; default: return NULL; } } { char buf[1] = {ch}; KLIB KBuffer_Write(kctx, &wb, (const char *)buf, 1); } text++; } return KLIB KBuffer_Stringfy(kctx, &wb, OnGcStack, StringPolicy_FreeKBuffer); }
static void kFile_format(KonohaContext *kctx, KonohaValue *v, int pos, KBuffer *wb) { kFile *file = (kFile *)v[pos].asObject; if(file->PathInfoNULL != NULL) { KLIB KBuffer_Write(kctx, wb, kString_text(file->PathInfoNULL), kString_size(file->PathInfoNULL)); } else { KLIB KBuffer_printf(kctx, wb, "FILE:%p", file->fp); } }
static kbool_t kNode_AddClassField(KonohaContext *kctx, kNode *stmt, kNameSpace *ns, KClassVar *definedClass, ktypeattr_t ty, kNode *expr) { if(expr->syn->keyword == KSymbol_LET) { // String name = "naruto"; kNode *lexpr = kNode_At(expr, 1); if(kNode_IsTerm(lexpr)) { kString *name = lexpr->TermToken->text; ksymbol_t symbol = KAsciiSymbol(kString_text(name), kString_size(name), KSymbol_NewId); kNode *vexpr = SUGAR TypeCheckNodeAt(kctx, expr, 2, ns, KClass_(ty), 0); if(vexpr == K_NULLNODE) return false; if(vexpr->node == KNode_Const) { KLIB KClass_AddField(kctx, definedClass, ty, symbol); KClass_SetClassFieldObjectValue(kctx, definedClass, symbol, vexpr->ObjectConstValue); } else if(vexpr->node == KNode_UnboxConst) { KLIB KClass_AddField(kctx, definedClass, ty, symbol); KClass_SetClassFieldUnboxValue(kctx, definedClass, symbol, vexpr->unboxConstValue); } else if(vexpr->node == KNode_Null) { KLIB KClass_AddField(kctx, definedClass, ty, symbol); } else { SUGAR MessageNode(kctx, stmt, lexpr->TermToken, ns, ErrTag, "field initial value must be const: %s", kString_text(name)); return false; } return true; } } else if(expr->syn->keyword == KSymbol_COMMA) { // String (firstName = naruto, lastName) size_t i; for(i = 1; i < kNode_GetNodeListSize(kctx, expr); i++) { if(!kNode_AddClassField(kctx, stmt, ns, definedClass, ty, kNode_At(expr, i))) return false; } return true; } else if(kNode_IsTerm(expr)) { // String name kString *name = expr->TermToken->text; ksymbol_t symbol = KAsciiSymbol(kString_text(name), kString_size(name), KSymbol_NewId); KLIB KClass_AddField(kctx, definedClass, ty, symbol); return true; } SUGAR MessageNode(kctx, stmt, NULL, ns, ErrTag, "field name is expected"); return false; }
//## @Public @Const @Immutable @Coercion String Symbol.toString(); static KMETHOD KSymbol_toString(KonohaContext *kctx, KonohaStack *sfp) { ksymbol_t symbol = (ksymbol_t)sfp[0].intValue; kString *s = KSymbol_GetString(kctx, KSymbol_Unmask(symbol)); if(KSymbol_Attr(symbol) != 0) { KBuffer wb; const char *prefix = KSymbol_prefixText(symbol); KLIB KBuffer_Init(&(kctx->stack->cwb), &wb); KLIB KBuffer_Write(kctx, &wb, prefix, strlen(prefix)); KLIB KBuffer_Write(kctx, &wb, kString_text(s), kString_size(s)); s = KLIB KBuffer_Stringfy(kctx, &wb, OnStack, StringPolicy_FreeKBuffer); } KReturn(s); }
//## Bytes String.toBytes(); static KMETHOD String_toBytes(KonohaContext *kctx, KonohaStack *sfp) { kString* thisString = sfp[0].asString; size_t size = kString_size(thisString); if(PLATAPI I18NModule.isSystemCharsetUTF8(kctx)) { KReturn(new_kBytes(kctx, OnStack, KGetReturnType(sfp), kString_text(thisString), size)); } else { KMakeTrace(trace, sfp); KBuffer wb; KLIB KBuffer_Init(&(kctx->stack->cwb), &wb); KBuffer_convertCharset(kctx, &wb, I18NAPI systemCharset, "UTF-8", kString_text(thisString), size, trace); KReturnWith( new_kBytes(kctx, OnStack, KGetReturnType(sfp), KLIB KBuffer_text(kctx, &wb, NonZero), KBuffer_bytesize(&wb)), KLIB KBuffer_Free(&wb) ); } }
//## boolean chdir(String path) static KMETHOD System_chdir(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX]; kString *path = sfp[1].asString; const char *systemPath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); int ret = chdir(systemPath); if(ret == -1) { KTraceErrorPoint(trace, SystemFault, "chdir", LogFileName(kString_text(path)), LogErrno); } KReturnUnboxValue(ret != -1); }
//## String System.realpath(String path) static KMETHOD System_realpath(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX], filepath[K_PATHMAX] = {0}; kString *path = sfp[1].asString; const char *systemPath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); char *cwd = realpath(systemPath, filepath); if(cwd != NULL) { const char *konohaPath = PLATAPI I18NModule.formatKonohaPath(kctx, buffer, sizeof(buffer), cwd, strlen(cwd), trace); KReturn(KLIB new_kString(kctx, OnStack, konohaPath, strlen(konohaPath), 0)); } else { KTraceErrorPoint(trace, SystemFault, "realpath", LogFileName(kString_text(path)), LogErrno); KReturn(KNULL(String)); } }
static kbool_t String_hasNext(KonohaContext *kctx, KonohaStack* sfp) { kIterator *itr = sfp[0].asIterator; kString *s = (kString *)itr->source; return (itr->current_pos < kString_size(s)); }
//## DIR System.opendir(String path) static KMETHOD System_opendir(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX]; kString *path = sfp[1].asString; const char *systemPath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); DIR *d = opendir(systemPath); if(d == NULL) { int fault = KLIB DiagnosisFaultType(kctx, kString_GuessUserFault(path)|SystemError, trace); KTraceErrorPoint(trace, fault, "opendir", LogText("dirname", kString_text(path)), LogErrno); KLIB KRuntime_raise(kctx, KException_("IO"), fault, NULL, sfp); } kDir *dir = (kDir *)KLIB new_kObject(kctx, OnStack, KGetReturnType(sfp), (uintptr_t)d); KFieldSet(dir, dir->PathInfoNULL, path); if(!PLATAPI I18NModule.isSystemCharsetUTF8(kctx)) { dir->readerIconv = PLATAPI I18NModule.iconvSystemCharsetToUTF8(kctx, trace); } KReturn(dir); }
//## boolean System.rmdir(String path) static KMETHOD System_rmdir(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX]; kString *path = sfp[1].asString; const char *systemPath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); int ret = rmdir(systemPath); if(ret == -1) { int fault = KLIB DiagnosisFaultType(kctx, kString_GuessUserFault(path)|SystemError, trace); KTraceErrorPoint(trace, fault, "rmdir", LogFileName(kString_text(path)), LogErrno); } else { KTraceChangeSystemPoint(trace, "rmdir", LogFileName(kString_text(path))); } KReturnUnboxValue(ret != -1); }
//## boolean System.isDir(String path) static KMETHOD System_isDir(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX]; kString *path = sfp[1].asString; const char *systemPath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); struct stat buf; if(stat(systemPath, &buf) == 0) { KReturnUnboxValue(S_ISDIR(buf.st_mode)); } KReturnUnboxValue(false); }
static KMETHOD System_readlink(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX]; kString *path = sfp[1].asString; const char *systemPath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); char pathbuf[K_PATHMAX]; ssize_t ret = readlink(systemPath, pathbuf, K_PATHMAX); if(ret == -1) { int fault = KLIB DiagnosisFaultType(kctx, kString_GuessUserFault(path)|SystemError, trace); KTraceErrorPoint(trace, fault, "readlink", LogFileName(kString_text(path)), LogErrno); KReturn(KNULL(String)); } else { const char *konohaPath = PLATAPI I18NModule.formatKonohaPath(kctx, buffer, sizeof(buffer), pathbuf, strlen(pathbuf), trace); KReturn(KLIB new_kString(kctx, OnStack, konohaPath, strlen(konohaPath), 0)); } }
static KMETHOD System_symlink(KonohaContext *kctx, KonohaStack *sfp) { char buffer[K_PATHMAX], buffer2[K_PATHMAX]; kString *path = sfp[1].asString, *path2 = sfp[2].asString; KMakeTrace(trace, sfp); const char *oldpath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); const char *newpath = PLATAPI I18NModule.formatSystemPath(kctx, buffer2, sizeof(buffer2), kString_text(path2), kString_size(path2), trace); int ret = symlink(oldpath, newpath); if(ret == -1) { int fault = KLIB DiagnosisFaultType(kctx, kString_GuessUserFault(path)|kString_GuessUserFault(path2)|SystemError, trace); KTraceErrorPoint(trace, fault, "symlink", LogFileName(kString_text(path)), LogFileName2(kString_text(path2)), LogErrno); } else { KTraceChangeSystemPoint(trace, "symlink", LogFileName(kString_text(path)), LogFileName2(kString_text(path2)), LogErrno); } KReturnUnboxValue(ret != -1); }
static KMETHOD Statement_class(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); kToken *tokenClassName = SUGAR kNode_GetToken(kctx, stmt, KSymbol_("$ClassName"), NULL); int isNewlyDefinedClass = false; KClassVar *definedClass = (KClassVar *)KLIB kNameSpace_GetClassByFullName(kctx, ns, kString_text(tokenClassName->text), kString_size(tokenClassName->text), NULL); if(definedClass == NULL) { // Already defined kshortflag_t cflag = kNode_ParseClassFlag(kctx, stmt, KClassFlag_Virtual); KMakeTraceUL(trace, sfp, kNode_uline(stmt)); definedClass = kNameSpace_DefineClassName(kctx, ns, cflag, tokenClassName->text, trace); isNewlyDefinedClass = true; } kNode *block = kNode_ParseClassNodeNULL(kctx, stmt, tokenClassName); size_t declsize = kNode_countFieldSize(kctx, block); if(isNewlyDefinedClass) { // Already defined KClass *superClass = KClass_Object; kToken *tokenSuperClass= SUGAR kNode_GetToken(kctx, stmt, KSymbol_("extends"), NULL); if(tokenSuperClass != NULL) { DBG_ASSERT(Token_isVirtualTypeLiteral(tokenSuperClass)); superClass = KClass_(Token_typeLiteral(tokenSuperClass)); if(KClass_Is(Final, superClass)) { KReturn(SUGAR MessageNode(kctx, stmt, NULL, ns, ErrTag, "%s is final", KClass_text(superClass))); } if(KClass_Is(Virtual, superClass)) { KReturn(SUGAR MessageNode(kctx, stmt, NULL, ns, ErrTag, "%s is still virtual", KClass_text(superClass))); } } size_t initsize = (block != NULL) ? declsize : initFieldSizeOfVirtualClass(superClass); KClass_InitField(kctx, definedClass, superClass, initsize); } else { if(declsize > 0 && !KClass_Is(Virtual, definedClass)) { KReturn(SUGAR MessageNode(kctx, stmt, NULL, ns, ErrTag, "%s has already defined", KClass_text(definedClass))); } } if(block != NULL) { if(!kNode_declClassField(kctx, block, ns, definedClass)) { KReturnUnboxValue(false); } KClass_Set(Virtual, definedClass, false); } kToken_SetTypeId(kctx, tokenClassName, ns, definedClass->typeId); kNode_AddMethodDeclNode(kctx, block, tokenClassName, stmt); KReturn(kNode_Type(kctx, stmt, KNode_Done, KType_void)); }
//## @Public @Const @Immutable @Coercion Symbol String.toSymbol(); static KMETHOD String_toSymbol(KonohaContext *kctx, KonohaStack *sfp) { KReturnUnboxValue(KAsciiSymbol(kString_text(sfp[0].asString), kString_size(sfp[0].asString), _NEWID)); }
//## FILE FILE.new(String path, String mode); static KMETHOD File_new(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX]; kString *path = sfp[1].asString; const char *systemPath = I18NAPI formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); const char *mode = kString_text(sfp[2].asString); FILE *fp = fopen(systemPath, mode); kFile *file = (kFile *) sfp[0].asObject; if(fp == NULL) { int fault = KLIB DiagnosisFaultType(kctx, kString_GuessUserFault(path)|SystemError, trace); KTraceErrorPoint(trace, fault, "fopen", LogText("filename", kString_text(path)), LogText("mode", mode), LogErrno); KLIB KRuntime_raise(kctx, KException_("IO"), fault, NULL, sfp); } if(mode[0] == 'w' || mode[0] == 'a' || mode[1] == '+') { KTraceChangeSystemPoint(trace, "fopen", LogFileName(kString_text(path)), LogText("mode", mode)); } file->fp = fp; KFieldInit(file, file->PathInfoNULL, path); if(!I18NAPI isSystemCharsetUTF8(kctx)) { if(mode[0] == 'w' || mode[0] == 'a' || mode[1] == '+') { file->writerIconv = I18NAPI iconvUTF8ToSystemCharset(kctx, trace); } else { file->readerIconv = I18NAPI iconvSystemCharsetToUTF8(kctx, trace); } } KReturn(file); }
//## Stat System.lstat(String path) static KMETHOD System_lstat(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX]; kString *path = sfp[1].asString; const char *systemPath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); struct stat buf = {}; /* zero */ #if defined(__MINGW32__) || defined(_MSC_VER) int ret = stat(systemPath, &buf); #else int ret = lstat(systemPath, &buf); #endif if(ret == -1) { int fault = KLIB DiagnosisFaultType(kctx, kString_GuessUserFault(path)|SystemError, trace); KTraceErrorPoint(trace, fault, "lstat", LogText("path", kString_text(path)), LogErrno); } KReturn(KLIB new_kObject(kctx, OnStack, KGetReturnType(sfp), (uintptr_t)&buf)); }
static KMETHOD System_lchown(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX]; kString *path = sfp[1].asString; const char *systemPath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); uid_t owner = (uid_t)sfp[2].intValue; gid_t group = (gid_t)sfp[3].intValue; int ret = lchown(systemPath, owner, group); if(ret == -1) { KTraceErrorPoint(trace, SystemFault, "lchown", LogFileName(kString_text(path)), LogOwner(owner), LogGroup(group), LogErrno); } KReturnUnboxValue(ret != -1); }