/* OpenIDA - Outil d'analyse de fichiers binaires
* variable.c - manipulation des variables en tout genre
*
* Copyright (C) 2008 Cyrille Bagard
*
* This file is part of OpenIDA.
*
* OpenIDA is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* OpenIDA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see .
*/
#include "variable.h"
#include
#include
#include
#include "../common/extstr.h"
/* ---------------------------- TYPES DE DONNEES SIMPLES ---------------------------- */
/* Variable représentant un argument ou un type de retour */
struct _simple_variable
{
BaseType type; /* Type représenté */
};
/* Décrit la variable simple sous forme de caractères. */
char *simple_var_to_string(const simple_variable *);
/* Supprime de la mémoire une variable de type simple. */
void delete_simple_var(simple_variable *);
/* --------------------- ENCAPSULATIONS DES VARIABLES COMPLEXES --------------------- */
/* Supprime de la mémoire une variable de type complexe. */
typedef void (* delete_complex_fc) (complex_variable *);
/* Décrit la variable complexe sous forme de caractères. */
typedef char * (* complex_to_string_fc) (const complex_variable *);
/* Représentation d'une variable complexe */
struct _complex_variable
{
delete_complex_fc delete; /* Procédure de suppression */
complex_to_string_fc to_string; /* Conversion en chaîne */
};
/* Initialise une représentation de variable complexe. */
void init_complex_var(complex_variable *);
/* Supprime de la mémoire une variable de type complexe. */
void delete_complex_var(complex_variable *);
/* Décrit la variable simple sous forme de caractères. */
char *complex_var_to_string(const complex_variable *);
/* ---------------------- VARIABLES DE CLASSES ET ENUMERATIONS ---------------------- */
/* Représentation des classes et des énumérations */
struct _class_enum_variable
{
complex_variable complex; /* A laisser en premier */
ClassEnumType type; /* Type représenté si connu */
char *desc; /* Description humaine */
};
/* Supprime de la mémoire une variable de classe/enumération. */
void delete_class_enum_var(class_enum_variable *);
/* Décrit la variable complexe sous forme de caractères. */
char *class_enum_var_to_string(const class_enum_variable *);
/* -------------------------- VARIABLES DEPENDANT D'AUTRES -------------------------- */
/* Représentation des variables dérivées */
struct _encapsulated_variable
{
complex_variable complex; /* A laisser en premier */
EncapsulationType type; /* Encapsulation utilisée */
variable *child; /* Sous-type encadré */
};
/* Supprime de la mémoire une variable dérivée. */
void delete_encapsulated_var(encapsulated_variable *);
/* Décrit la variable dérivée sous forme de caractères. */
char *encapsulated_var_to_string(const encapsulated_variable *);
/* ---------------------- MANIPULATION GENERIQUE DES VARIABLES ---------------------- */
/* Variable représentant un argument ou un type de retour */
struct _variable
{
union
{
simple_variable *simple; /* Variable simple */
complex_variable *complex; /* Variable plus compliquée */
} value;
bool is_simple; /* Choix du champ valide */
VariableQualifier qualifiers; /* Eventuels qualificatifs */
};
/* ---------------------------------------------------------------------------------- */
/* TYPES DE DONNEES SIMPLES */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : - *
* *
* Description : Crée une représentation de variable. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
simple_variable *create_simple_var(void)
{
simple_variable *result; /* Structure à retourner */
result = (simple_variable *)calloc(1, sizeof(simple_variable));
return result;
}
/******************************************************************************
* *
* Paramètres : type = type de base à représenter. *
* *
* Description : Crée une représentation de variable à type connu. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
simple_variable *create_typed_simple_var(BaseType type)
{
simple_variable *result; /* Structure à retourner */
result = create_simple_var();
set_simple_var_type(result, type);
return result;
}
/******************************************************************************
* *
* Paramètres : var = variable à effacer. *
* *
* Description : Supprime de la mémoire une variable de type simple. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void delete_simple_var(simple_variable *var)
{
free(var);
}
/******************************************************************************
* *
* Paramètres : var = variable à mettre à jour. *
* type = type de base à représenter. *
* *
* Description : Définit le type d'une variable simple. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void set_simple_var_type(simple_variable *var, BaseType type)
{
var->type = type;
}
/******************************************************************************
* *
* Paramètres : var = variable à consulter. *
* *
* Description : Décrit la variable simple sous forme de caractères. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
char *simple_var_to_string(const simple_variable *var)
{
char *result; /* Chaîne à renvoyer */
switch (var->type)
{
case BTP_VOID:
result = "void";
break;
case BTP_WCHAR_T:
result = "wchar_t";
break;
case BTP_BOOL:
result = "bool";
break;
case BTP_CHAR:
result = "char";
break;
case BTP_SCHAR:
result = "signed char";
break;
case BTP_UCHAR:
result = "unsigned char";
break;
case BTP_SHORT:
result = "short";
break;
case BTP_USHORT:
result = "unsigned short";
break;
case BTP_INT:
result = "int";
break;
case BTP_UINT:
result = "unsigned int";
break;
case BTP_LONG:
result = "long";
break;
case BTP_ULONG:
result = "unsigned long";
break;
case BTP_LONG_LONG:
result = "long long";
break;
case BTP_ULONG_LONG:
result = "unsigned long long";
break;
case BTP_INT128:
result = "__int128";
break;
case BTP_UINT128:
result = "__uint128";
break;
case BTP_FLOAT:
result = "float";
break;
case BTP_DOUBLE:
result = "double";
break;
case BTP_LONG_DOUBLE:
result = "__float80";
break;
case BTP_FLOAT128:
result = "__float128";
break;
case BTP_ELLIPSIS:
result = "...";
break;
case BTP_754R_64:
result = "754r_float64";
break;
case BTP_754R_128:
result = "754r_float128";
break;
case BTP_754R_32:
result = "754r_float32";
break;
case BTP_754R_16:
result = "754r_float16";
break;
case BTP_CHAR32_T:
result = "char32_t";
break;
case BTP_CHAR16_T:
result = "char16_t";
break;
case BTP_OTHER:
result = "[toto]"; /* FIXME */
break;
default:
result = "/* pour gcc */";
break;
}
result = strdup(result);
return result;
}
/* ---------------------------------------------------------------------------------- */
/* ENCAPSULATIONS DES VARIABLES COMPLEXES */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : var = structure vierge à préparer. *
* *
* Description : Initialise une représentation de variable complexe. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
void init_complex_var(complex_variable *var)
{
}
/******************************************************************************
* *
* Paramètres : var = variable à effacer. *
* *
* Description : Supprime de la mémoire une variable de type complexe. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void delete_complex_var(complex_variable *var)
{
var->delete(var);
}
/******************************************************************************
* *
* Paramètres : var = variable à consulter. *
* *
* Description : Décrit la variable complexe sous forme de caractères. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
char *complex_var_to_string(const complex_variable *var)
{
return var->to_string(var);
}
/* ---------------------------------------------------------------------------------- */
/* VARIABLES DE CLASSES ET ENUMERATIONS */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : type = type de base à représenter. *
* desc = description humaine de la variable. *
* *
* Description : Crée une représentation de variable de classe/enumération. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : La description ne doit pas être libérée par l'appelant ! *
* *
******************************************************************************/
complex_variable *create_class_enum_var(char *desc)
{
class_enum_variable *result; /* Structure à retourner */
result = (class_enum_variable *)calloc(1, sizeof(class_enum_variable));
init_complex_var(COMPLEX_VAR(result));
COMPLEX_VAR(result)->delete = (delete_complex_fc)delete_class_enum_var;
COMPLEX_VAR(result)->to_string = (complex_to_string_fc)class_enum_var_to_string;
result->desc = desc;
return COMPLEX_VAR(result);
}
/******************************************************************************
* *
* Paramètres : var = variable à effacer. *
* *
* Description : Supprime de la mémoire une variable de classe/enumération. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void delete_class_enum_var(class_enum_variable *var)
{
free(var->desc);
free(var);
}
/******************************************************************************
* *
* Paramètres : var = variable à consulter. *
* *
* Description : Décrit la variable complexe sous forme de caractères. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
char *class_enum_var_to_string(const class_enum_variable *var)
{
return strdup(var->desc);
}
/* ---------------------------------------------------------------------------------- */
/* VARIABLES DEPENDANT D'AUTRES */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : type = type d'extension à représenter. *
* child = variable dont on doit dériver. *
* *
* Description : Crée une représentation de variable dérivée. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
complex_variable *create_encapsulated_var(EncapsulationType type, variable *child)
{
encapsulated_variable *result; /* Structure à retourner */
result = (encapsulated_variable *)calloc(1, sizeof(encapsulated_variable));
init_complex_var(COMPLEX_VAR(result));
COMPLEX_VAR(result)->delete = (delete_complex_fc)delete_encapsulated_var;
COMPLEX_VAR(result)->to_string = (complex_to_string_fc)encapsulated_var_to_string;
result->type = type;
result->child = child;
return COMPLEX_VAR(result);
}
/******************************************************************************
* *
* Paramètres : var = variable à effacer. *
* *
* Description : Supprime de la mémoire une variable dérivée. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void delete_encapsulated_var(encapsulated_variable *var)
{
delete_var(var->child);
free(var);
}
/******************************************************************************
* *
* Paramètres : var = variable à consulter. *
* *
* Description : Décrit la variable dérivée sous forme de caractères. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
char *encapsulated_var_to_string(const encapsulated_variable *var)
{
char *result; /* Chaîne finale à renvoyer */
result = var_to_string(var->child);
switch (var->type)
{
case ECT_POINTER:
if (result[strlen(result) - 1] == '*') result = stradd(result, "*");
else result = stradd(result, " *");
break;
case ECT_REFERENCE:
result = stradd(result, " &");
break;
case ECT_RVALUE_REF:
result = stradd(result, " [[rval ???]]") /* FIXME */;
break;
case ECT_COMPLEX:
result = stradd(result, " complex");
break;
case ECT_IMAGINARY:
result = stradd(result, " imaginary");
break;
}
return result;
}
/* ---------------------------------------------------------------------------------- */
/* MANIPULATION GENERIQUE DES VARIABLES */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : var = variable à emballer. *
* *
* Description : Crée une représentation de variable (simple). *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
variable *create_var_from_simple_one(simple_variable *var)
{
variable *result; /* Structure à retourner */
result = (variable *)calloc(1, sizeof(variable));
result->value.simple = var;
result->is_simple = true;
return result;
}
/******************************************************************************
* *
* Paramètres : var = variable à emballer. *
* *
* Description : Crée une représentation de variable (complexe). *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
variable *create_var_from_complex_one(complex_variable *var)
{
variable *result; /* Structure à retourner */
result = (variable *)calloc(1, sizeof(variable));
result->value.complex = var;
result->is_simple = false;
return result;
}
/******************************************************************************
* *
* Paramètres : var = variable à effecer. *
* *
* Description : Supprime la représentation de variable de la mémoire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void delete_var(variable *var)
{
if (var->is_simple) delete_simple_var(var->value.simple);
else delete_complex_var(var->value.complex);
free(var);
}
/******************************************************************************
* *
* Paramètres : var = variable à mettre à jour. *
* qualifier = nouveau qualificatif pour la variable. *
* *
* Description : Ajoute un qualificatif à la variable. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void add_qualifier_to_var(variable *var, VariableQualifier qualifier)
{
var->qualifiers |= qualifier;
}
/******************************************************************************
* *
* Paramètres : var = variable à consulter. *
* *
* Description : Décrit la variable sous forme de caractères. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
char *var_to_string(const variable *var)
{
char *result; /* Chaîne à renvoyer */
if (var->is_simple) result = simple_var_to_string(var->value.simple);
else result = complex_var_to_string(var->value.complex);
if (var->qualifiers & VQF_RESTRICT)
strprep(result, "restrict ");
if (var->qualifiers & VQF_VOLATILE)
strprep(result, "volatile ");
if (var->qualifiers & VQF_CONST)
strprep(result, "const ");
return result;
}