Files

324 lines
9.4 KiB
Plaintext
Raw Permalink Normal View History

## vim: ft=makocpp
2022-05-11 17:05:25 +02:00
<%
api = java_api
nat = c_api.get_name
options_type = capi.get_name('gpr_options')
2022-05-11 17:05:25 +02:00
project_type = capi.get_name('gpr_project')
str_array_type = capi.get_name('string_array_ptr')
sig_base = "com/adacore/" + ctx.lib_name.lower + "/" + ctx.lib_name.camel
ptr_sig = sig_base + "$PointerWrapper"
%>
void add_error_to_diagnostics(
JNIEnv *env,
jstring error,
jobject diagnostics
) {
// Get the "add" method of the list
jclass clazz = (*env)->GetObjectClass(env, diagnostics);
jmethodID add_id = (*env)-> GetMethodID(
env,
clazz,
"add",
"(Ljava/lang/Object;)Z"
);
// Call the "add" method with the Java string to add it to the diagnostics
(*env)->CallVoidMethod(env, diagnostics, add_id, error);
}
${api.jni_func_sig("gpr_options_create", "jobject")}(
JNIEnv *env,
jclass jni_lib
) {
${options_type} options = ${nat("gpr_options_create")}();
return PointerWrapper_wrap(env, (void *) options);
}
${api.jni_func_sig("gpr_options_add_switch", "void")}(
JNIEnv *env,
jclass jni_lib,
jobject options,
jint switchKind,
jstring param,
jstring index,
jboolean overwrite
) {
${options_type} c_options = get_reference(env, options);
const char *c_param = param == NULL ? NULL : to_c_string(env, param);
const char *c_index = index == NULL ? NULL : to_c_string(env, index);
${nat("gpr_options_add_switch")}(
c_options,
(int) switchKind,
c_param,
c_index,
(int) overwrite
);
if (c_param != NULL)
(*env)->ReleaseStringUTFChars(env, param, c_param);
if (c_index != NULL)
(*env)->ReleaseStringUTFChars(env, index, c_index);
}
${api.jni_func_sig("gpr_options_free", "void")}(
JNIEnv *env,
jclass jni_lib,
jobject options
) {
${options_type} c_options = get_reference(env, options);
${nat("gpr_options_free")}(c_options);
}
2022-05-11 17:05:25 +02:00
// Load a gpr project
${api.jni_func_sig("gpr_project_load", "jobject")}(
JNIEnv *env,
jclass jni_lib,
jobject options,
2024-09-24 11:50:15 +02:00
jboolean ada_only,
jobject diagnostics
2022-05-11 17:05:25 +02:00
) {
${options_type} c_options = get_reference(env, options);
2022-05-11 17:05:25 +02:00
${project_type} res = NULL;
${str_array_type} errors = NULL;
${nat("gpr_project_load")}(c_options, (int) ada_only, &res, &errors);
2022-05-11 17:05:25 +02:00
// The `errors` pointer is not allocated if an exception was raised during
// project file loading.
if (errors != NULL) {
// Handle the errors
for(int i = 0 ; i < errors->length ; i++) {
const char *error = errors->c_ptr[i];
jstring j_error = (*env)->NewStringUTF(env, error);
add_error_to_diagnostics(env, j_error, diagnostics);
2022-05-11 17:05:25 +02:00
}
// Free the error array
${nat("free_string_array")}(errors);
}
// Return the pointer
return PointerWrapper_wrap(env, (void *) res);
}
// Free a gpr project
${api.jni_func_sig("gpr_project_free", "void")}(
JNIEnv *env,
jclass jni_lib,
jobject project
) {
// Do the native call
${nat("gpr_project_free")}((${project_type}) get_reference(env, project));
}
// Get the unit provider from a gpr project
${api.jni_func_sig("gpr_project_create_unit_provider", "jobject")}(
JNIEnv *env,
jclass jni_lib,
jobject project,
jstring subproject
2022-05-11 17:05:25 +02:00
) {
const char* subproject_c = NULL;
if (subproject != NULL) {
subproject_c = (*env)->GetStringUTFChars(env, subproject, NULL);
}
2022-05-11 17:05:25 +02:00
// Call the native function
${unit_provider_type} res = ${nat("gpr_project_create_unit_provider")}(
(${project_type}) get_reference(env, project),
subproject_c
2022-05-11 17:05:25 +02:00
);
// Free all temporarily allocated memory
if (subproject_c != NULL) {
(*env)->ReleaseStringUTFChars(env, subproject, subproject_c);
}
2022-05-11 17:05:25 +02:00
// Return the new unit provider
return UnitProvider_wrap(env, res);
}
// Get the list of the files of a project
${api.jni_func_sig("gpr_project_source_files", "jobjectArray")}(
JNIEnv *env,
jclass jni_lib,
jobject project,
jint mode,
jobjectArray subprojects
2022-05-11 17:05:25 +02:00
) {
jobjectArray result_java = NULL;
/* Convert the Java array of subprojects ("subprojects" argument) into the
required C array (subproject_count/subprojects_c). */
jsize subproject_count = 0;
const char** subprojects_c = NULL;
if (subprojects != NULL)
{
subproject_count = (*env)->GetArrayLength (env, subprojects);
subprojects_c = calloc (subproject_count, sizeof (char*));
}
for (int i = 0; i < subproject_count; ++i)
{
jstring subproject
= (jstring) (*env)->GetObjectArrayElement (env, subprojects, i);
subprojects_c[i] = (*env)->GetStringUTFChars (env, subproject, NULL);
}
/* Call the C API. In case of failure, return NULL and let the caller
propagate the native exception into the Java world. */
${str_array_type} result_c = ${nat("gpr_project_source_files")} (
(${project_type}) get_reference (env, project),
2022-05-11 17:05:25 +02:00
(int) mode,
subprojects_c,
subproject_count
2022-05-11 17:05:25 +02:00
);
if (${nat("get_last_exception")} () != NULL)
goto error;
2022-05-11 17:05:25 +02:00
/* Create the Java array result and initialize it. */
jclass clazz = (*env)->FindClass (env, "java/lang/String");
result_java
= (*env)->NewObjectArray (env, (jsize) result_c->length, clazz, NULL);
for (int i = 0 ; i < result_c->length ; i++)
{
jstring source_file
= to_j_string (env, result_c->c_ptr[i]);
(*env)->SetObjectArrayElement (env, result_java, (jsize) i,
(jobject) source_file);
}
2022-05-11 17:05:25 +02:00
/* Now that the Java result is ready, release the C result. */
${nat("free_string_array")} (result_c);
2022-05-11 17:05:25 +02:00
error:
/* Release subprojects_c. */
for (int i = 0; i < subproject_count; ++i)
{
jstring subproject
= (jstring) (*env)->GetObjectArrayElement(env, subprojects, i);
(*env)->ReleaseStringUTFChars (env, subproject, subprojects_c[i]);
}
free (subprojects_c);
2022-05-11 17:05:25 +02:00
return result_java;
2022-05-11 17:05:25 +02:00
}
${c_doc("libadalang.gpr_project_create_context", lang="java")}
${api.jni_func_sig("gpr_project_create_context", "jobject")}(
JNIEnv *env,
jclass jni_lib,
jobject project,
jstring subproject,
jobject event_handler,
jboolean with_trivia,
jint tab_stop
)
{
const char *subproject_c = NULL;
if (subproject != NULL)
subproject_c = (*env)->GetStringUTFChars (env, subproject, NULL);
${event_handler_type} event_handler_c = NULL;
if (event_handler != NULL)
event_handler_c = EventHandler_unwrap (env, event_handler);
/* Manually allocate a C-level analysis context so that we can initialize
it ourselves. */
${analysis_context_type} ctx_c = ${nat("allocate_analysis_context")} ();
/* Create the Java wrapper, so that we have one ready for event handler
callbacks triggered during context initialization. */
jobject ctx = AnalysisContext_wrap (env, ctx_c);
/* The wrapper created its own ownership share: release ours. */
${nat("context_decref")} (ctx_c);
/* TODO: attach extra wrappers to the analysis context wrapper so that
wrappers ("project" and "event_handler") live at least as long as the
analysis context. */
/* Finally, initialize the analysis context. Note that this step may raise
an exception: in that case, the analysis context is considered not
initialized: release it. */
${nat("gpr_project_initialize_context")} (
(${project_type}) get_reference (env, project),
ctx_c,
subproject_c,
event_handler_c,
(int) with_trivia,
(int) tab_stop
);
if (subproject_c != NULL)
(*env)->ReleaseStringUTFChars (env, subproject, subproject_c);
const ${exception_type} *exc_c = ${nat("get_last_exception")} ();
if (exc_c != NULL)
{
jthrowable exc = LangkitException_wrap (env, *exc_c);
${nat("context_decref")} (ctx_c);
(*env)->Throw (env, exc);
}
return ctx;
}
// Create an auto provider reference
${api.jni_func_sig("create_auto_provider", "jobject")}(
JNIEnv *env,
jclass jni_lib,
jobjectArray source_files,
jstring charset
) {
// Retrieve the number of files N
jsize source_file_count = (*env)->GetArrayLength(env, source_files);
// Allocate an array of N+1 element (the last one should be the null pointer),
// indicating the end of the C array.
const char** source_files_c = calloc(source_file_count + 1, sizeof(char*));
for (int i = 0; i < source_file_count; ++i) {
jstring source_file = (jstring) (*env)->GetObjectArrayElement(
env,
source_files,
i
);
source_files_c[i] = (*env)->GetStringUTFChars(env, source_file, NULL);
}
const char* charset_c = NULL;
if (charset != NULL) {
charset_c = (*env)->GetStringUTFChars(env, charset, NULL);
}
// Create the auto provider
${unit_provider_type} res = ${nat("create_auto_provider")}(
source_files_c, charset_c
);
// Free all temporarily allocated memory
if (charset_c != NULL) {
(*env)->ReleaseStringUTFChars(env, charset, charset_c);
}
for (int i = 0; i < source_file_count; ++i) {
jstring source_file = (jstring) (*env)->GetObjectArrayElement(
env,
source_files,
i
);
(*env)->ReleaseStringUTFChars(env, source_file, source_files_c[i]);
}
free(source_files_c);
// Return the new unit provider
return UnitProvider_wrap(env, res);
}