/* 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 Chrysalide. 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 = get_input_buffer_next_char(buffer);
ahead != '\0';
ahead = get_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 = get_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;
}