You've already forked libadalang
mirror of
https://github.com/AdaCore/libadalang.git
synced 2026-02-12 12:28:54 -08:00
361 lines
10 KiB
Plaintext
361 lines
10 KiB
Plaintext
## vim: ft=makocpp
|
|
|
|
<%
|
|
api = java_api
|
|
nat = c_api.get_name
|
|
|
|
options_type = capi.get_name('gpr_options')
|
|
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);
|
|
}
|
|
|
|
// Load a gpr project
|
|
${api.jni_func_sig("gpr_project_load", "jobject")}(
|
|
JNIEnv *env,
|
|
jclass jni_lib,
|
|
jobject options,
|
|
jboolean ada_only,
|
|
jobject diagnostics
|
|
) {
|
|
${options_type} c_options = get_reference(env, options);
|
|
${project_type} res = NULL;
|
|
${str_array_type} errors = NULL;
|
|
|
|
${nat("gpr_project_load")}(c_options, (int) ada_only, &res, &errors);
|
|
|
|
// 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);
|
|
}
|
|
|
|
// 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
|
|
) {
|
|
const char* subproject_c = NULL;
|
|
|
|
if (subproject != NULL) {
|
|
subproject_c = (*env)->GetStringUTFChars(env, subproject, NULL);
|
|
}
|
|
|
|
// Call the native function
|
|
${unit_provider_type} res = ${nat("gpr_project_create_unit_provider")}(
|
|
(${project_type}) get_reference(env, project),
|
|
subproject_c
|
|
);
|
|
|
|
// Free all temporarily allocated memory
|
|
if (subproject_c != NULL) {
|
|
(*env)->ReleaseStringUTFChars(env, subproject, subproject_c);
|
|
}
|
|
|
|
// 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
|
|
) {
|
|
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),
|
|
(int) mode,
|
|
subprojects_c,
|
|
subproject_count
|
|
);
|
|
if (${nat("get_last_exception")} () != NULL)
|
|
goto error;
|
|
|
|
/* 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);
|
|
}
|
|
|
|
/* Now that the Java result is ready, release the C result. */
|
|
${nat("free_string_array")} (result_c);
|
|
|
|
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);
|
|
|
|
return result_java;
|
|
}
|
|
|
|
${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);
|
|
}
|
|
|
|
${api.jni_func_sig("set_config_pragmas_mapping", "void")}(
|
|
JNIEnv *env,
|
|
jclass jni_lib,
|
|
jobject context,
|
|
jobject global_pragmas,
|
|
jobjectArray local_pragmas
|
|
) {
|
|
ada_analysis_context context_c;
|
|
ada_analysis_unit global_pragmas_c;
|
|
ada_analysis_unit *local_pragmas_c;
|
|
int i, size;
|
|
|
|
context_c = AnalysisContext_unwrap (env, context);
|
|
global_pragmas_c
|
|
= (global_pragmas == NULL)
|
|
? NULL
|
|
: AnalysisUnit_unwrap (env, global_pragmas);
|
|
|
|
size = (*env)->GetArrayLength (env, local_pragmas);
|
|
local_pragmas_c = calloc (size, sizeof (ada_analysis_unit));
|
|
for (i = 0; i < size; ++i)
|
|
{
|
|
jobject unit_java
|
|
= (*env)->GetObjectArrayElement (env, local_pragmas, (jsize) i);
|
|
ada_analysis_unit unit_c;
|
|
|
|
unit_c
|
|
= (unit_java == NULL) ? NULL : AnalysisUnit_unwrap (env, unit_java);
|
|
local_pragmas_c[i] = unit_c;
|
|
}
|
|
|
|
${nat("set_config_pragmas_mapping")} (context_c, global_pragmas_c,
|
|
local_pragmas_c);
|
|
|
|
free (local_pragmas_c);
|
|
}
|