/* Chrysalide - Outil d'analyse de fichiers binaires
* pproc.c - remplacements à la volée de chaînes de caractères
*
* Copyright (C) 2014-2017 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* Chrysalide 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.
*
* Chrysalide 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 Chrysalide. If not, see .
*/
#include "pproc.h"
#include
#include
/* Pré-processeur avec support des macros */
struct _pre_processor
{
string_exch *encodings; /* Traductions d'encodages */
size_t encodings_count; /* Nombre de ces traductions */
string_exch *macros; /* Remplacements de chaînes */
size_t macros_count; /* Nombre de ces remplacements */
const char **op_producers; /* Producteurs d'opérandes */
size_t op_prod_count; /* Quantité de producteurs */
};
/******************************************************************************
* *
* Paramètres : - *
* *
* Description : Crée un nouveau pre-processeur pour le support des macros. *
* *
* Retour : Nouvelle structure prête à emploi. *
* *
* Remarques : - *
* *
******************************************************************************/
pre_processor *create_pre_processor(void)
{
pre_processor *result; /* Définition vierge à renvoyer*/
result = (pre_processor *)calloc(1, sizeof(pre_processor));
return result;
}
/******************************************************************************
* *
* Paramètres : pp = pré-processeur à libérer de la mémoire. *
* *
* Description : Supprime de la mémoire un pré-processeur et ses macros. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void delete_pre_processor(pre_processor *pp)
{
if (pp->encodings != NULL)
free(pp->encodings);
if (pp->macros != NULL)
free(pp->macros);
free(pp);
}
/******************************************************************************
* *
* Paramètres : pp = pré-processeur dont le contenu est à compléter. *
* *
* Description : Enregistre une correspondance nule en matière d'encodage. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void register_empty_encoding(pre_processor *pp)
{
string_exch *encoding; /* Traduction à conserver */
pp->encodings = (string_exch *)realloc(pp->encodings, ++pp->encodings_count * sizeof(string_exch));
encoding = &pp->encodings[pp->encodings_count - 1];
encoding->src = NULL;
encoding->dest = NULL;
}
/******************************************************************************
* *
* Paramètres : pp = pré-processeur dont le contenu est à compléter. *
* src = chaîne à remplacer dans les définitions. *
* dest = chaîne de remplacement. *
* *
* Description : Enregistre une correspondance en matière d'encodage. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void register_encoding(pre_processor *pp, const char *src, const char *dest)
{
string_exch *encoding; /* Traduction à conserver */
pp->encodings = (string_exch *)realloc(pp->encodings, ++pp->encodings_count * sizeof(string_exch));
encoding = &pp->encodings[pp->encodings_count - 1];
encoding->src = src;
encoding->dest = dest;
}
/******************************************************************************
* *
* Paramètres : pp = pré-processeur dont le contenu est à consulter. *
* *
* Description : Indique le nombre de catégories d'encodages enregistrées. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
size_t count_encodings(const pre_processor *pp)
{
return pp->encodings_count;
}
/******************************************************************************
* *
* Paramètres : pp = pré-processeur dont le contenu est à consulter. *
* index = indice de l'encodage à retourner. *
* *
* Description : Fournit une catégorie d'encodage donnée. *
* *
* Retour : Correspondance à consulter uniquement. *
* *
* Remarques : - *
* *
******************************************************************************/
const string_exch *find_encoding(const pre_processor *pp, size_t index)
{
return &pp->encodings[index];
}
/******************************************************************************
* *
* Paramètres : pp = pré-processeur dont le contenu est à compléter. *
* src = chaîne à remplacer dans les définitions. *
* dest = chaîne de remplacement. *
* *
* Description : Constitue la matière d'un système de macros. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void define_macro(pre_processor *pp, const char *src, const char *dest)
{
string_exch *macro; /* Nouvelle macro à constituer */
pp->macros = (string_exch *)realloc(pp->macros, ++pp->macros_count * sizeof(string_exch));
macro = &pp->macros[pp->macros_count - 1];
macro->src = src;
macro->dest = dest;
}
/******************************************************************************
* *
* Paramètres : pp = pré-processeur dont le contenu est à consulter. *
* src = chaîne à remplacer dans les définitions. *
* *
* Description : Recherche l'existence d'une macro pour un remplacement. *
* *
* Retour : Eventuelle correspondance trouvée. *
* *
* Remarques : - *
* *
******************************************************************************/
const char *find_macro(const pre_processor *pp, const char *src)
{
const char *result; /* Trouvaille à renvoyer */
size_t i; /* Boucle de parcours */
result = NULL;
for (i = 0; i < pp->macros_count && result == NULL; i++)
if (strcmp(pp->macros[i].src, src) == 0)
result = pp->macros[i].dest;
return result;
}
/******************************************************************************
* *
* Paramètres : pp = pré-processeur dont le contenu est à compléter. *
* func = fonction produisant un opérande final. *
* *
* Description : Mémorise une fonction comme produisant un opérateur final. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void register_as_operand_producer(pre_processor *pp, const char *func)
{
pp->op_producers = (const char **)realloc(pp->op_producers, ++pp->op_prod_count * sizeof(const char **));
pp->op_producers[pp->op_prod_count - 1] = func;
}
/******************************************************************************
* *
* Paramètres : pp = pré-processeur dont le contenu est à consulter. *
* func = fonction dont la nature du résultat est recherchée. *
* *
* Description : Détermine si une fonction produit un opérande ou non. *
* *
* Retour : true si la fonction fournie produit un opérande final. *
* *
* Remarques : - *
* *
******************************************************************************/
bool is_operand_producer(const pre_processor *pp, const char *func)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
result = false;
for (i = 0; i < pp->op_prod_count && !result; i++)
result = (strcmp(pp->op_producers[i], func) == 0);
return result;
}