/* 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; }