예제 #1
0
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;
}
예제 #2
0
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);
    }
}
예제 #3
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);
	}
}
예제 #4
0
//## 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));
}
예제 #5
0
// 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);
}
예제 #6
0
//## 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));
}
예제 #7
0
/* 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);
}
예제 #8
0
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);
	}
}
예제 #9
0
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;
}
예제 #10
0
//## @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);
}
예제 #11
0
//## 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)
		);
	}
}
예제 #12
0
//## 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);
}
예제 #13
0
//## 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));
	}
}
예제 #14
0
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));
}
예제 #15
0
//## 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);
}
예제 #16
0
//## 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);
}
예제 #17
0
//## 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);
}
예제 #18
0
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));
	}
}
예제 #19
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);
}
예제 #20
0
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));
}
예제 #21
0
//## @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));
}
예제 #22
0
//## 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);
}
예제 #23
0
//## 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));
}
예제 #24
0
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);
}