self.header.add_decl("#include <stdio.h>")
self.header.add_decl("#include <string.h>")
self.header.add_decl("#include \"gc_chooser.h\"")
+ self.header.add_decl("#ifdef ANDROID")
+ self.header.add_decl(" #include <android/log.h>")
+ self.header.add_decl(" #define PRINT_ERROR(...) (void)__android_log_print(ANDROID_LOG_WARN, \"Nit\", __VA_ARGS__)")
+ self.header.add_decl("#else")
+ self.header.add_decl(" #define PRINT_ERROR(...) fprintf(stderr, __VA_ARGS__)")
+ self.header.add_decl("#endif")
compile_header_structs
compile_nitni_structs
end
v.add_decl("void sig_handler(int signo)\{")
- v.add_decl("printf(\"Caught signal : %s\\n\", strsignal(signo));")
+ v.add_decl("PRINT_ERROR(\"Caught signal : %s\\n\", strsignal(signo));")
v.add_decl("show_backtrace(signo);")
v.add_decl("\}")
v.add_decl("char* procname = malloc(sizeof(char) * 100);")
v.add_decl("unw_getcontext(&uc);")
v.add_decl("unw_init_local(&cursor, &uc);")
- v.add_decl("printf(\"-------------------------------------------------\\n\");")
- v.add_decl("printf(\"-- Stack Trace ------------------------------\\n\");")
- v.add_decl("printf(\"-------------------------------------------------\\n\");")
+ v.add_decl("PRINT_ERROR(\"-------------------------------------------------\\n\");")
+ v.add_decl("PRINT_ERROR(\"-- Stack Trace ------------------------------\\n\");")
+ v.add_decl("PRINT_ERROR(\"-------------------------------------------------\\n\");")
v.add_decl("while (unw_step(&cursor) > 0) \{")
v.add_decl(" unw_get_proc_name(&cursor, procname, 100, &ip);")
if ost == "nitstack" then
v.add_decl(" const char* recv = get_nit_name(procname, strlen(procname));")
v.add_decl(" if (recv != NULL)\{")
- v.add_decl(" printf(\"` %s\\n\", recv);")
+ v.add_decl(" PRINT_ERROR(\"` %s\\n\", recv);")
v.add_decl(" \}else\{")
- v.add_decl(" printf(\"` %s\\n\", procname);")
+ v.add_decl(" PRINT_ERROR(\"` %s\\n\", procname);")
v.add_decl(" \}")
else
- v.add_decl(" printf(\"` %s \\n\",procname);")
+ v.add_decl(" PRINT_ERROR(\"` %s \\n\",procname);")
end
v.add_decl("\}")
- v.add_decl("printf(\"-------------------------------------------------\\n\");")
+ v.add_decl("PRINT_ERROR(\"-------------------------------------------------\\n\");")
v.add_decl("free(procname);")
v.add_decl("\}")
end
# used by aborts, asserts, casts, etc.
fun add_abort(message: String)
do
- self.add("fprintf(stderr, \"Runtime error: %s\", \"{message.escape_to_c}\");")
+ self.add("PRINT_ERROR(\"Runtime error: %s\", \"{message.escape_to_c}\");")
add_raw_abort
end
fun add_raw_abort
do
if self.current_node != null and self.current_node.location.file != null then
- self.add("fprintf(stderr, \" (%s:%d)\\n\", \"{self.current_node.location.file.filename.escape_to_c}\", {current_node.location.line_start});")
+ self.add("PRINT_ERROR(\" (%s:%d)\\n\", \"{self.current_node.location.file.filename.escape_to_c}\", {current_node.location.line_start});")
else
- self.add("fprintf(stderr, \"\\n\");")
+ self.add("PRINT_ERROR(\"\\n\");")
end
self.add("show_backtrace(1);")
end
var res = self.type_test(value, mtype, tag)
self.add("if (unlikely(!{res})) \{")
var cn = self.class_name_string(value)
- self.add("fprintf(stderr, \"Runtime error: Cast failed. Expected `%s`, got `%s`\", \"{mtype.to_s.escape_to_c}\", {cn});")
+ self.add("PRINT_ERROR(\"Runtime error: Cast failed. Expected `%s`, got `%s`\", \"{mtype.to_s.escape_to_c}\", {cn});")
self.add_raw_abort
self.add("\}")
end
redef class APropdef
fun compile_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable])
do
- v.add("printf(\"NOT YET IMPLEMENTED {class_name} {mpropdef} at {location.to_s}\\n\");")
+ v.add("PRINT_ERROR(\"NOT YET IMPLEMENTED {class_name} {mpropdef} at {location.to_s}\\n\");")
debug("Not yet implemented")
end
v.ret(v.new_expr("glob_argv[{arguments[1]}]", ret.as(not null)))
return
end
- v.add("printf(\"NOT YET IMPLEMENTED {class_name}:{mpropdef} at {location.to_s}\\n\");")
+ v.add("PRINT_ERROR(\"NOT YET IMPLEMENTED {class_name}:{mpropdef} at {location.to_s}\\n\");")
debug("Not implemented {mpropdef}")
end
end
var externname
var nextern = self.n_extern
if nextern == null then
- v.add("fprintf(stderr, \"NOT YET IMPLEMENTED nitni for {mpropdef} at {location.to_s}\\n\");")
+ v.add("PRINT_ERROR(\"NOT YET IMPLEMENTED nitni for {mpropdef} at {location.to_s}\\n\");")
v.add("show_backtrace(1);")
return
end
var externname
var nextern = self.n_extern
if nextern == null then
- v.add("printf(\"NOT YET IMPLEMENTED nitni for {mpropdef} at {location.to_s}\\n\");")
+ v.add("PRINT_ERROR(\"NOT YET IMPLEMENTED nitni for {mpropdef} at {location.to_s}\\n\");")
v.add("show_backtrace(1);")
return
end
redef class ADeferredMethPropdef
redef fun compile_to_c(v, mpropdef, arguments) do
var cn = v.class_name_string(arguments.first)
- v.add("fprintf(stderr, \"Runtime error: Abstract method `%s` called on `%s`\", \"{mpropdef.mproperty.name.escape_to_c}\", {cn});")
+ v.add("PRINT_ERROR(\"Runtime error: Abstract method `%s` called on `%s`\", \"{mpropdef.mproperty.name.escape_to_c}\", {cn});")
v.add_raw_abort
end
redef fun can_inline do return true
# Do not call this method directly, use `v.expr` instead
private fun expr(v: AbstractCompilerVisitor): nullable RuntimeVariable
do
- v.add("printf(\"NOT YET IMPLEMENTED {class_name}:{location.to_s}\\n\");")
+ v.add("PRINT_ERROR(\"NOT YET IMPLEMENTED {class_name}:{location.to_s}\\n\");")
var mtype = self.mtype
if mtype == null then
return null
ffi_ccu.header_c_base.add( "#include \"{mmodule.name}._nitni.h\"\n" )
+ ffi_ccu.body_decl.add("#ifdef ANDROID\n")
+ ffi_ccu.body_decl.add(" #include <android/log.h>\n")
+ ffi_ccu.body_decl.add(" #define PRINT_ERROR(...) (void)__android_log_print(ANDROID_LOG_WARN, \"Nit\", __VA_ARGS__)\n")
+ ffi_ccu.body_decl.add("#else\n")
+ ffi_ccu.body_decl.add(" #define PRINT_ERROR(...) fprintf(stderr, __VA_ARGS__)\n")
+ ffi_ccu.body_decl.add("#endif\n")
+
for nclassdef in n_classdefs do
# Does it declares an extern type?
if nclassdef isa AStdClassdef and nclassdef.n_extern_code_block != null then
// retrieve the implementation Java class
java_class = (*nit_ffi_jni_env)->FindClass(nit_ffi_jni_env, "{{{mmodule.impl_java_class_name}}}");
+ if (java_class == NULL) {
+ PRINT_ERROR("Nit FFI with Java error: failed to load class.\\n");
+ (*nit_ffi_jni_env)->ExceptionDescribe(nit_ffi_jni_env);
+ exit(1);
+ }
// register callbacks (only once per Nit module)
if (!nit_ffi_with_java_registered_natives) nit_ffi_with_java_register_natives(nit_ffi_jni_env, java_class);
// retreive the implementation static function
java_meth_id = (*nit_ffi_jni_env)->GetStaticMethodID(nit_ffi_jni_env, java_class, "{{{java_fun_name}}}", "{{{jni_format}}}");
if (java_meth_id == NULL) {
- fprintf(stderr, "Nit FFI with Java error: Java implementation not found.\\n");
+ PRINT_ERROR("Nit FFI with Java error: Java implementation not found.\\n");
(*nit_ffi_jni_env)->ExceptionDescribe(nit_ffi_jni_env);
exit(1);
}
// execute implementation code
{{{ccall}}}
if ((*nit_ffi_jni_env)->ExceptionCheck(nit_ffi_jni_env)) {
- fprintf(stderr, "Nit FFI with Java error: Exception after call.\\n");
+ PRINT_ERROR("Nit FFI with Java error: Exception after call.\\n");
(*nit_ffi_jni_env)->ExceptionDescribe(nit_ffi_jni_env);
exit(1);
}
};
jint res = (*env)->RegisterNatives(env, jclazz, methods, n_methods);
if (res != JNI_OK) {
- fprintf(stderr, "RegisterNatives failed\\n");
+ PRINT_ERROR("RegisterNatives failed\\n");
(*env)->ExceptionDescribe(env);
exit(1);
}
var res = self.new_var(mtype)
if not compiler.runtime_type_analysis.live_types.has(valtype) then
self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
- self.add("printf(\"Dead code executed!\\n\"); show_backtrace(1);")
+ self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
return res
end
self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
# Bad things will appen!
var res = self.new_var(mtype)
self.add("/* {res} left unintialized (cannot convert {value.mtype} to {mtype}) */")
- self.add("printf(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
+ self.add("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
return res
end
end
fun bugtype(recv: RuntimeVariable)
do
if recv.mtype.ctype != "val*" then return
- self.add("fprintf(stderr, \"BTD BUG: Dynamic type is %s, static type is %s\\n\", class_names[{recv}->classid], \"{recv.mcasttype}\");")
+ self.add("PRINT_ERROR(\"BTD BUG: Dynamic type is %s, static type is %s\\n\", class_names[{recv}->classid], \"{recv.mcasttype}\");")
self.add("show_backtrace(1);")
end
v.add_abort("type null")
v.add("\}")
v.add("if({t}->table_size == 0) \{")
- v.add("fprintf(stderr, \"Insantiation of a dead type: %s\\n\", {t}->name);")
+ v.add("PRINT_ERROR(\"Insantiation of a dead type: %s\\n\", {t}->name);")
v.add_abort("type dead")
v.add("\}")
end
var res = self.new_var(mtype)
if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(valtype) then
self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
- self.add("printf(\"Dead code executed!\\n\"); show_backtrace(1);")
+ self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
return res
end
self.require_declaration("BOX_{valtype.c_name}")
# Bad things will appen!
var res = self.new_var(mtype)
self.add("/* {res} left unintialized (cannot convert {value.mtype} to {mtype}) */")
- self.add("printf(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
+ self.add("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
return res
end
end
self.require_declaration(mtype.const_color)
var col = mtype.const_color
self.add("if({col} == -1) \{")
- self.add("fprintf(stderr, \"Resolution of a dead open type: %s\\n\", \"{mtype.to_s.escape_to_c}\");")
+ self.add("PRINT_ERROR(\"Resolution of a dead open type: %s\\n\", \"{mtype.to_s.escape_to_c}\");")
self.add_abort("open type dead")
self.add("\}")
end
add_abort("cast type null")
add("\}")
add("if({t}->id == -1 || {t}->color == -1) \{")
- add("fprintf(stderr, \"Try to cast on a dead cast type: %s\\n\", {t}->name);")
+ add("PRINT_ERROR(\"Try to cast on a dead cast type: %s\\n\", {t}->name);")
add_abort("cast type dead")
add("\}")
end
self.add("count_type_test_resolved_{tag}++;")
end
else
- self.add("printf(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{value.inspect}\"); show_backtrace(1);")
+ self.add("PRINT_ERROR(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{value.inspect}\"); show_backtrace(1);")
end
# check color is in table
self.add("if (!{cond}) \{")
#var x = self.class_name_string(res)
#var y = self.class_name_string(arguments.first)
- #self.add("fprintf(stderr, \"Erasure cast: expected {mtype} (self is %s), got %s for {res}\\n\", {y}, {x});")
+ #self.add("PRINT_ERROR(\"Erasure cast: expected {mtype} (self is %s), got %s for {res}\\n\", {y}, {x});")
self.add_abort("Cast failed")
self.add("\}")
end