summaryrefslogtreecommitdiff
path: root/src/analysis/scan/exprs/call.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/scan/exprs/call.c')
-rw-r--r--src/analysis/scan/exprs/call.c223
1 files changed, 86 insertions, 137 deletions
diff --git a/src/analysis/scan/exprs/call.c b/src/analysis/scan/exprs/call.c
index 76f5fc3..dde627c 100644
--- a/src/analysis/scan/exprs/call.c
+++ b/src/analysis/scan/exprs/call.c
@@ -24,6 +24,7 @@
#include "call.h"
+#include <assert.h>
#include <malloc.h>
#include <string.h>
@@ -48,19 +49,16 @@ static void g_pending_call_dispose(GPendingCall *);
/* Procède à la libération totale de la mémoire. */
static void g_pending_call_finalize(GPendingCall *);
-/* Définit une base de recherche pour la cible d'appel. */
-static void g_pending_call_set_base(GPendingCall *, GRegisteredItem *);
-
/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
/* Reproduit une expression en place dans une nouvelle instance. */
-static GScanExpression *g_pending_call_duplicate(const GPendingCall *);
+static void g_pending_call_copy(GPendingCall *, const GPendingCall *);
/* Réduit une expression à une forme plus simple. */
-GScanExpression *g_pending_call_reduce(GPendingCall *, GScanContext *, bool);
+static bool g_pending_call_reduce(GPendingCall *, GScanContext *, GScanScope *, GScanExpression **);
@@ -70,7 +68,7 @@ GScanExpression *g_pending_call_reduce(GPendingCall *, GScanContext *, bool);
/* Indique le type défini pour un appel de fonction enregistrée. */
-G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_SCAN_EXPRESSION);
+G_DEFINE_TYPE(GPendingCall, g_pending_call, G_TYPE_NAMED_ACCESS);
/******************************************************************************
@@ -98,7 +96,7 @@ static void g_pending_call_class_init(GPendingCallClass *klass)
expr = G_SCAN_EXPRESSION_CLASS(klass);
expr->cmp_rich = (compare_expr_rich_fc)NULL;
- expr->dup = (dup_expr_fc)g_pending_call_duplicate;
+ expr->copy = (copy_expr_fc)g_pending_call_copy;
expr->reduce = (reduce_expr_fc)g_pending_call_reduce;
}
@@ -118,14 +116,9 @@ static void g_pending_call_class_init(GPendingCallClass *klass)
static void g_pending_call_init(GPendingCall *call)
{
- call->base = NULL;
- call->target = NULL;
-
call->args = NULL;
call->count = 0;
- call->next = NULL;
-
}
@@ -145,13 +138,9 @@ static void g_pending_call_dispose(GPendingCall *call)
{
size_t i; /* Boucle de parcours */
- g_clear_object(&call->base);
-
for (i = 0; i < call->count; i++)
g_clear_object(&call->args[i]);
- g_clear_object(&call->next);
-
G_OBJECT_CLASS(g_pending_call_parent_class)->dispose(G_OBJECT(call));
}
@@ -171,9 +160,6 @@ static void g_pending_call_dispose(GPendingCall *call)
static void g_pending_call_finalize(GPendingCall *call)
{
- if (call->target != NULL)
- free(call->target);
-
if (call->args != NULL)
free(call->args);
@@ -185,7 +171,6 @@ static void g_pending_call_finalize(GPendingCall *call)
/******************************************************************************
* *
* Paramètres : target = désignation de l'objet d'appel à identifier. *
-* len = taille de cette désignation. *
* args = éventuelle liste d'arguments à actionner. *
* count = quantité de ces arguments. *
* *
@@ -197,13 +182,13 @@ static void g_pending_call_finalize(GPendingCall *call)
* *
******************************************************************************/
-GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpression **args, size_t count)
+GScanExpression *g_pending_call_new(const sized_string_t *target, GScanExpression **args, size_t count)
{
GScanExpression *result; /* Structure à retourner */
result = g_object_new(G_TYPE_PENDING_CALL, NULL);
- if (!g_pending_call_create(G_PENDING_CALL(result), target, len, args, count))
+ if (!g_pending_call_create(G_PENDING_CALL(result), target, args, count))
g_clear_object(&result);
return result;
@@ -215,7 +200,6 @@ GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpress
* *
* Paramètres : call = instance à initialiser pleinement. *
* target = désignation de l'objet d'appel à identifier. *
-* len = taille de cette désignation. *
* args = éventuelle liste d'arguments à actionner. *
* count = quantité de ces arguments. *
* *
@@ -227,16 +211,14 @@ GScanExpression *g_pending_call_new(const char *target, size_t len, GScanExpress
* *
******************************************************************************/
-bool g_pending_call_create(GPendingCall *call, const char *target, size_t len, GScanExpression **args, size_t count)
+bool g_pending_call_create(GPendingCall *call, const sized_string_t *target, GScanExpression **args, size_t count)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
- result = g_scan_expression_create(G_SCAN_EXPRESSION(call), EVT_PENDING);
+ result = g_named_access_create(G_NAMED_ACCESS(call), target);
if (!result) goto exit;
- call->target = strndup(target, len);
-
call->args = malloc(count * sizeof(GScanExpression *));
call->count = count;
@@ -253,48 +235,6 @@ bool g_pending_call_create(GPendingCall *call, const char *target, size_t len, G
}
-/******************************************************************************
-* *
-* Paramètres : call = expression d'appel à actualiser. *
-* base = zone de recherche pour la résolution à venir. *
-* *
-* Description : Définit une base de recherche pour la cible d'appel. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_pending_call_set_base(GPendingCall *call, GRegisteredItem *base)
-{
- call->base = base;
- g_object_ref(G_OBJECT(base));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : call = expression d'appel à compléter. *
-* next = expression d'appel suivante dans la chaîne. *
-* *
-* Description : Complète la chaine d'expressions d'appel. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_pending_call_attach_next(GPendingCall *call, GPendingCall *next)
-{
- call->next = next;
- g_object_ref(G_OBJECT(next));
-
-}
-
-
/* ---------------------------------------------------------------------------------- */
/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
@@ -303,23 +243,31 @@ void g_pending_call_attach_next(GPendingCall *call, GPendingCall *next)
/******************************************************************************
* *
-* Paramètres : expr = expression à copier. *
+* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] *
+* src = expression source à copier. *
* *
* Description : Reproduit une expression en place dans une nouvelle instance.*
* *
-* Retour : Nouvelle instance d'expression. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static GScanExpression *g_pending_call_duplicate(const GPendingCall *expr)
+static void g_pending_call_copy(GPendingCall *dest, const GPendingCall *src)
{
- GScanExpression *result; /* Instance copiée à retourner */
+ GScanExpressionClass *class; /* Classe parente à solliciter */
+ size_t i; /* Boucle de parcours */
- result = g_pending_call_new(expr->target, strlen(expr->target), expr->args, expr->count);
+ class = G_SCAN_EXPRESSION_CLASS(g_pending_call_parent_class);
- return result;
+ class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src));
+
+ dest->args = malloc(src->count * sizeof(GScanExpression *));
+ dest->count = src->count;
+
+ for (i = 0; i < src->count; i++)
+ dest->args[i] = g_scan_expression_duplicate(src->args[i]);
}
@@ -328,99 +276,100 @@ static GScanExpression *g_pending_call_duplicate(const GPendingCall *expr)
* *
* Paramètres : expr = expression à consulter. *
* ctx = contexte de suivi de l'analyse courante. *
-* final = indique une ultime conversion dans le cycle en cours.*
+* scope = portée courante des variables locales. *
+* out = zone d'enregistrement de la réduction opérée. [OUT] *
* *
* Description : Réduit une expression à une forme plus simple. *
* *
-* Retour : Réduction correspondante, expression déjà réduite, ou NULL. *
+* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. *
* *
* Remarques : - *
* *
******************************************************************************/
-GScanExpression *g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, bool final)
+static bool g_pending_call_reduce(GPendingCall *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out)
{
- GScanExpression *result; /* Instance à renvoyer */
+ bool result; /* Bilan à retourner */
+ GNamedAccess *new; /* Eventuel étage suivant */
+ GPendingCall *new_call; /* Version en appel */
size_t i; /* Boucle de parcours */
- GScanExpression *new; /* Nouvelle expression obtenue */
- bool last; /* Détection de fin de chaîne */
- GRegisteredItem *base; /* Base de recherche courante */
- GRegisteredItem *rebase; /* Nouvelle base résolue */
+ GScanExpression *arg; /* Argument réduit à échanger */
+ GObject *final; /* Expression ou élément ? */
GScanExpression *new_next; /* Nouvelle version du suivant */
- for (i = 0; i < expr->count; i++)
+ result = _g_named_access_reduce(G_NAMED_ACCESS(expr), ctx, scope, out);
+
+ if (result && *out != NULL)
{
- new = g_scan_expression_reduce(expr->args[i], ctx, final);
+ assert(G_IS_NAMED_ACCESS(*out));
- if (new != NULL)
- {
- g_object_unref(G_OBJECT(expr->args[i]));
- expr->args[i] = new;
- }
+ new = G_NAMED_ACCESS(*out);
+ *out = NULL;
- }
+ assert(new->target == NULL);
+ assert(G_IS_PENDING_CALL(new));
+ assert(G_IS_REGISTERED_ITEM(new->resolved));
- last = (expr->next == NULL);
+ new_call = G_PENDING_CALL(new);
- if (!last)
- new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(expr->next));
- else
- new_next = NULL;
-
- if (expr->target != NULL)
- {
- if (expr->base != NULL)
+ for (i = 0; i < new_call->count; i++)
{
- base = expr->base;
- g_object_ref(G_OBJECT(base));
- }
- else
- base = G_REGISTERED_ITEM(get_rost_root_namespace());
+ result = g_scan_expression_reduce(new_call->args[i], ctx, scope, &arg);
+ if (!result) goto exit;
- rebase = g_registered_item_resolve(base, expr->target, ctx,
- last ? NULL : expr->args, last ? 0 : expr->count,
- last, final);
+ if (arg != NULL)
+ {
+ g_object_unref(G_OBJECT(new_call->args[i]));
+ new_call->args[i] = arg;
+ }
- g_object_unref(G_OBJECT(base));
- if (rebase == NULL)
- {
- result = NULL;
- goto done;
}
- if (last)
- {
- g_pending_call_set_base(expr, rebase);
+ result = g_registered_item_run_call(new->resolved,
+ new_call->args,
+ new_call->count,
+ ctx, scope, &final);
- free(expr->target);
- expr->target = NULL;
+ if (result && final != NULL)
+ {
+ /**
+ * Si le produit de l'appel à la fonction est une expression d'évaluation
+ * classique, alors ce produit constitue la réduction finale de la chaîne.
+ *
+ * Ce cas de figure ne se rencontre normalement qu'en bout de chaîne.
+ */
+ if (!G_IS_REGISTERED_ITEM(final))
+ {
+ assert(new->next == NULL);
+ *out = G_SCAN_EXPRESSION(final);
+ }
+ else
+ {
+ assert(new->next != NULL);
+
+ new_next = g_scan_expression_duplicate(G_SCAN_EXPRESSION(new->next));
+ assert(G_IS_NAMED_ACCESS(new_next));
+
+ g_named_access_set_base(G_NAMED_ACCESS(new_next), G_REGISTERED_ITEM(final));
+
+ result = g_scan_expression_reduce(new_next, ctx, scope, out);
+
+ if (result && *out == NULL)
+ *out = new_next;
+ else
+ g_object_unref(G_OBJECT(new_next));
+
+ }
}
- else
- g_pending_call_set_base(G_PENDING_CALL(new_next), rebase);
-
- }
- if (last)
- result = g_registered_item_reduce(expr->base, ctx, expr->args, expr->count, final);
+ exit:
- else
- {
- result = g_scan_expression_reduce(new_next, ctx, final);
-
- if (result == NULL)
- {
- g_object_ref(G_OBJECT(new_next));
- result = new_next;
- }
+ g_object_unref(G_OBJECT(new));
}
- done:
-
- g_clear_object(&new_next);
-
return result;
}