/*
 * freescope - Free source browser
 * Copyright (C) 2001  Olivier Deme
 * 
 * This program 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 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

// FILE:        cli.cpp

/************/
/* INCLUDES */
/************/

#include <signal.h>
#include <iostream>
#include <strstream>
#include "cli.h"
#include "siglink.h"
#include "fconfig.h"


/***************/
/* DEFINITIONS */
/***************/

#define ctrl(x) (x & 037)


/************************/
/* FUNCTION DEFINITIONS */
/************************/

/*
 * FUNCTION:    Cli::do_init
 *
 * DESCRIPTION: Initialises CLI
 *
 * IN:
 * IN-OUT:
 * OUT:
 * RETURN CODE:
 * SIDE EFFECT:
 */

void Cli::do_init () throw (DbUser_Exception)
{
    // Exit the application if we receive the SIGPIPE signal
    try
    {
        SIGLINK->Register(SIGPIPE, on_sigpipe, this);
    }
    catch (SigLink_Exception& se)
    {
        throw(DbUser_Exception(se.what()));
    }

    // Update database
    if (FCONFIG->get_update_on_startup() == true)
        update ();
}

/*
 * FUNCTION:    Cli::display_result
 *
 * DESCRIPTION: This function goest through the list of matches and
 *              displays the resuts on the screen.
 *
 * THROW:
 * IN: 
 * IN-OUT:
 * RETURN CODE:
 */

void Cli::display_result ()
{
    list<match_t>::iterator it;

    cout << "cscope: " << m_result.size() << " lines" << endl;

    for (it = m_result.begin(); it != m_result.end(); ++it)
    {
        switch(m_query_type)
        {
        case QUERY_SYMBOL:
        case QUERY_CALLED:
        case QUERY_CALL:
        case QUERY_DEFINITION: cout << it->file << " " << it->scope << " " 
                                    << it->lineno << " " 
                                    << read_line(it->file, it->lineno) << endl;
                               break;
        case QUERY_INCLUDE:
        case QUERY_REGEXP:
        case QUERY_TEXT:       cout << it->file << " . " << it->lineno << " "
                                    << read_line(it->file, it->lineno) << endl;
                               break;
        case QUERY_FILE:       cout << it->file << " . . ." <<endl;
                               break;
        default:               break;
        }
    }
}
    
/*
 * FUNCTION:    Cli::terminate
 *
 * DESCRIPTION: This function is called when a fatal error causes the program
 *              to terminate abnormally.
 *
 * IN:          reason          The reason for termination
 * IN-OUT:
 * OUT:
 * RETURN CODE:
 */

void Cli::terminate (const string& reason)
{
    if (reason.size() != 0)
        cerr << reason << endl;
    exit(-1);
}

/*
 * FUNCTION:    Cli::do_loop
 *
 * DESCRIPTION: This function starts the main processing loop for the CLI.
 *
 * IN:
 * IN-OUT:
 * OUT:
 * RETURN CODE:
 * SIDE EFFECT:
 */

void Cli::do_loop ()
{
    string       query;
    bool         is_query;

    for (;;)
    {
        // Display the prompt
        cout << ">> ";
        cout.flush();

        // Get the query
        cin >> query;

        is_query = false;

        // Process query
        switch (query[0])
        {
            case '0':   m_query_type = QUERY_SYMBOL;
                        is_query   = true;
                        break;
            case '1':   m_query_type = QUERY_DEFINITION;
                        is_query   = true;
                        break;
            case '2':   m_query_type = QUERY_CALLED;
                        is_query   = true;
                        break;
            case '3':   m_query_type = QUERY_CALL;
                        is_query   = true;
                        break;
            case '4':   m_query_type = QUERY_TEXT;
                        is_query   = true;
                        break;
            case '5':   m_query_type = QUERY_NOT_SUPPORTED;
                        is_query   = true;
                        break;
            case '6':   m_query_type = QUERY_REGEXP;
                        is_query   = true;
                        break;
            case '7':   m_query_type = QUERY_FILE;
                        is_query   = true;
                        break;
            case '8':   m_query_type = QUERY_INCLUDE;
                        is_query   = true;
                        break;
            case '9':   m_query_type = QUERY_NOT_SUPPORTED;
                        is_query   = true;
                        break;
            case 'r':
            case 'R':   update();
                        break;
            case 'Q':
            case 'q':   exit(0);
            default:    cerr << "freescope: unknown command" << endl;
                        break;
        }

        if (is_query == true)
        {
            query.erase(0, 1);
            do_query(m_query_type, query);
        }
    }
}

/*
 * FUNCTION:    Cli::on_sigpipe
 *
 * DESCRIPTION: This function is called if freescope receives the SIGPIPE signal
 *
 * IN:          signo           The signal caught
 *              arg             A pointer ro the CLI instance
 * IN-OUT:
 * OUT:
 * RETURN CODE:
 * SIDE EFFECT:
 */

void Cli::on_sigpipe (int   signo,
                      void* arg)
{
    cerr << "Received SIGPIPE signal. Exiting..." << endl;
    exit(0);
}


syntax highlighted by Code2HTML, v. 0.9.1