/* Chrysalide - Outil d'analyse de fichiers binaires
 * output.c - sorties en langage de programmation
 *
 * Copyright (C) 2010-2013 Cyrille Bagard
 *
 *  This file is part of Chrysalide.
 *
 *  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 <http://www.gnu.org/licenses/>.
 */


#include "output.h"


#include "output-int.h"
#include "../analysis/type.h" /* TODO : remme */



/* Indique le type défini pour une sortie de langage de programmation. */
G_DEFINE_TYPE(GLangOutput, g_lang_output, G_TYPE_OBJECT);


/******************************************************************************
*                                                                             *
*  Paramètres  : klass = classe à initialiser.                                *
*                                                                             *
*  Description : Initialise la classe des sorties en langage de programmation.*
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_lang_output_class_init(GLangOutputClass *klass)
{

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = instance à initialiser.                             *
*                                                                             *
*  Description : Initialise une instance de sortie en langage de prog.        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_lang_output_init(GLangOutput *output)
{

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                                                                             *
*  Description : Marque le début d'une série de commentaires.                 *
*                                                                             *
*  Retour      : Nouvelle ligne constituée.                                   *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_start_comments(GLangOutput *output, GCodeBuffer *buffer)
{
    GBufferLine *result;                    /* Adresse nouvelle à remonter */

    if (output->start_comments != NULL)
        result = output->start_comments(output, buffer);

    else result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                text   = texte à insérer dans l'existant.                    *
*                length = taille du texte à traiter.                          *
*                                                                             *
*  Description : Poursuit l'ajout d'une ligne de commentaires.                *
*                                                                             *
*  Retour      : Ligne nouvellement créée.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_continue_comments(GLangOutput *output, GCodeBuffer *buffer, const char *text, size_t length)
{
    GBufferLine *result;                    /* Adresse nouvelle à remonter */

    if (output->cont_comments != NULL)
        result = output->cont_comments(output, buffer, text, length);

    else result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                                                                             *
*  Description : Marque la fin d'une série de commentaires.                   *
*                                                                             *
*  Retour      : Nouvelle ligne constituée.                                   *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_end_comments(GLangOutput *output, GCodeBuffer *buffer)
{
    GBufferLine *result;                    /* Adresse nouvelle à remonter */

    if (output->end_comments != NULL)
        result = output->end_comments(output, buffer);

    else result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                text   = texte à insérer dans l'existant.                    *
*                length = taille du texte à traiter.                          *
*                                                                             *
*  Description : Ajoute un commentaire à un tampon donné.                     *
*                                                                             *
*  Retour      : Ligne nouvellement créée.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_write_comments(GLangOutput *output, GCodeBuffer *buffer, const char *text, size_t length)
{
    GBufferLine *result;                    /* Adresse nouvelle à remonter */

    if (output->write_comments != NULL)
        result = output->write_comments(output, buffer, text, length);

    else result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                line   = tampon de sortie à disposition.                     *
*                sign   = méthode de comparaison à imprimer.                  *
*                                                                             *
*  Description : Imprime dans un tampon donné une méthode de comparaison.     *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_lang_output_write_comp_sign(GLangOutput *output, GBufferLine *line, CompSignType sign)
{
    if (output->comp_sign != NULL)
        output->comp_sign(output, line, sign);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                line   = tampon de sortie à disposition.                     *
*                op     = opérateur logique à imprimer.                       *
*                                                                             *
*  Description : Imprime dans un tampon donné un opérateur logique.           *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_lang_output_write_cond_operator(GLangOutput *output, GBufferLine *line, CondOperatorType op)
{
    if (output->cond_op != NULL)
        output->cond_op(output, line, op);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                type   = désignation de la classe à définir.                 *
*                                                                             *
*  Description : Débute la définition d'une classe.                           *
*                                                                             *
*  Retour      : Ligne nouvellement créée.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_start_class(GLangOutput *output, GCodeBuffer *buffer, const void *type)
{
    GBufferLine *result;                    /* Adresse nouvelle à remonter */

    if (output->start_class != NULL)
        result = output->start_class(output, buffer, (const GDataType *)type);

    else result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                                                                             *
*  Description : Termine la définition d'une classe.                          *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_lang_output_end_class(GLangOutput *output, GCodeBuffer *buffer)
{
    if (output->end_class != NULL)
        output->end_class(output, buffer);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                                                                             *
*  Description : Débute la documentation d'une routine.                       *
*                                                                             *
*  Retour      : Ligne nouvellement créée.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_start_routine_info(const GLangOutput *output, GCodeBuffer *buffer)
{
    GBufferLine *result;                    /* Adresse nouvelle à remonter */

    if (output->start_routine_proto != NULL)
    {
        result = output->start_info(output, buffer);
        g_buffer_line_start_merge_at(result, BLC_LAST_USED);
    }
    else result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                ret    = type de retour de la routine traitée.               *
*                                                                             *
*  Description : Débute la définition d'une routine.                          *
*                                                                             *
*  Retour      : Ligne nouvellement créée.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_start_routine_prototype(GLangOutput *output, GCodeBuffer *buffer, const void *ret)
{
    GBufferLine *result;                    /* Adresse nouvelle à remonter */

    if (output->start_routine_proto != NULL)
        result = output->start_routine_proto(output, buffer, ret);

    else result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                line   = ligne contenant le prototype de la routine traitée. *
*                                                                             *
*  Description : Termine la définition d'une routine.                         *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_lang_output_end_routine_prototype(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line)
{
    if (output->end_routine_proto != NULL)
        output->end_routine_proto(output, buffer, line);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                line   = ligne contenant le prototype de la routine traitée. *
*                                                                             *
*  Description : Commence la définition du corps d'une routine.               *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_lang_output_start_routine_body(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line)
{
    if (output->start_routine_body != NULL)
        output->start_routine_body(output, buffer, line);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                                                                             *
*  Description : Termine la définition du corps d'une routine.                *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_lang_output_end_routine_body(GLangOutput *output, GCodeBuffer *buffer)
{
    if (output->end_routine_body != NULL)
        output->end_routine_body(output, buffer);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                line   = ligne contenant le prototype de la routine traitée. *
*                count  = nombre d'éléments du bloc.                          *
*                                                                             *
*  Description : Commence la définition d'un bloc de code.                    *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_start_code_block(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count)
{
    GBufferLine *result;                    /* Nouvelle ligne à utiliser   */

    if (output->start_code_block != NULL)
        result = output->start_code_block(output, buffer, line, count);
    else
        result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output = encadrant de l'impression en langage de prog.       *
*                buffer = tampon de sortie à disposition.                     *
*                line   = ligne contenant le prototype de la routine traitée. *
*                count  = nombre d'éléments du bloc.                          *
*                                                                             *
*  Description : Termine la définition d'un bloc de code.                     *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_end_code_block(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, size_t count)
{
    GBufferLine *result;                    /* Nouvelle ligne à utiliser   */

    if (output->end_code_block != NULL)
        result = output->end_code_block(output, buffer, line, count);
    else
        result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : output  = encadrant de l'impression en langage de prog.      *
*                buffer  = tampon de sortie à disposition.                    *
*                line    = ligne contenant le prototype de la routine traitée.*
*                opening = précise si la condition débute ou se termine.      *
*                                                                             *
*  Description : Emballe une expression conditionelle.                        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBufferLine *g_lang_output_encapsulate_condition(GLangOutput *output, GCodeBuffer *buffer, GBufferLine *line, bool opening)
{
    GBufferLine *result;                    /* Nouvelle ligne à utiliser   */

    if (output->encaps_cond != NULL)
        result = output->encaps_cond(output, buffer, line, opening);
    else
        result = NULL;

    return result;

}