/* Chrysalide - Outil d'analyse de fichiers binaires * shorty.c - décodage de routines pour Dex * * Copyright (C) 2018 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 Foobar. If not, see . */ #include "shorty.h" #include #include /* Extrait un type particulier dans un décodage Dex. */ static GDataType *dsd_shorty_return_type(input_buffer *); /* Extrait un type particulier dans un décodage Dex. */ static GDataType *dsd_shorty_field_type(input_buffer *, char); /****************************************************************************** * * * Paramètres : buffer = tampon contenant les données utiles. * * * * Description : Extrait un routine particulière depuis un codage Dex. * * * * Retour : Nouveau type mis en place ou NULL en cas d'erreur. * * * * Remarques : - * * * ******************************************************************************/ GBinRoutine *dsd_shorty_descriptor(input_buffer *buffer) { GBinRoutine *result; /* Type à retourner */ GDataType *type; /* Description de type obtenue */ char ahead; /* Caractère déterminant lu */ GBinVariable *var; /* Argument de routine */ /** * La règle traitée est la suivante : * * ShortyDescriptor → * ShortyReturnType (ShortyFieldType)* * */ result = g_binary_routine_new(); /* Retour */ type = dsd_shorty_return_type(buffer); if (type == NULL) goto dsd_error; else g_binary_routine_set_return_type(result, type); /* Arguments */ for (ahead = text_input_buffer_next_char(buffer); ahead != '\0'; ahead = text_input_buffer_next_char(buffer)) { type = dsd_shorty_field_type(buffer, ahead); if (type == NULL) goto dsd_error; else { var = g_binary_variable_new(type); g_binary_routine_add_arg(result, var); } } return result; dsd_error: g_object_unref(G_OBJECT(result)); return NULL; } /****************************************************************************** * * * Paramètres : buffer = tampon contenant les données utiles. * * * * Description : Extrait un type particulier dans un décodage Dex. * * * * Retour : Nouveau type mis en place ou NULL en cas d'erreur. * * * * Remarques : - * * * ******************************************************************************/ static GDataType *dsd_shorty_return_type(input_buffer *buffer) { GDataType *result; /* Type à retourner */ char ahead; /* Caractère déterminant lu */ /** * La règle traitée est la suivante : * * ShortyReturnType → * 'V' * | ShortyFieldType * */ ahead = text_input_buffer_next_char(buffer); if (ahead == 'V') result = g_basic_type_new(BTP_VOID); else result = dsd_shorty_field_type(buffer, ahead); return result; } /****************************************************************************** * * * Paramètres : buffer = tampon contenant les données utiles. * * ahead = caractère déjà dépilé de ces données. * * * * Description : Extrait un type particulier dans un décodage Dex. * * * * Retour : Nouveau type mis en place ou NULL en cas d'erreur. * * * * Remarques : - * * * ******************************************************************************/ static GDataType *dsd_shorty_field_type(input_buffer *buffer, char ahead) { GDataType *result; /* Type à retourner */ /** * La règle traitée est la suivante : * * ShortyFieldType → * 'Z' * | 'B' * | 'S' * | 'C' * | 'I' * | 'J' * | 'F' * | 'D' * | 'L' * */ switch (ahead) { case 'Z': result = g_basic_type_new(BTP_BOOL); break; case 'B': result = g_basic_type_new(BTP_UCHAR); break; case 'S': result = g_basic_type_new(BTP_SHORT); break; case 'C': result = g_basic_type_new(BTP_CHAR); break; case 'I': result = g_basic_type_new(BTP_INT); break; case 'J': result = g_basic_type_new(BTP_LONG); break; case 'F': result = g_basic_type_new(BTP_FLOAT); break; case 'D': result = g_basic_type_new(BTP_DOUBLE); break; case 'L': result = g_class_enum_type_new(CET_CLASS, NULL); break; default: result = NULL; break; } return result; }