// $Id$
// Read in VSL library

// Copyright (C) 1995 Technische Universitaet Braunschweig, Germany.
// Copyright (C) 2000 Universitaet Passau, Germany.
// Written by Andreas Zeller <zeller@gnu.org>.
// 
// This file is part of DDD.
// 
// DDD 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.
// 
// DDD 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 DDD -- see the file COPYING.
// If not, see <http://www.gnu.org/licenses/>.
// 
// DDD is the data display debugger.
// For details, see the DDD World-Wide-Web page, 
// `http://www.gnu.org/software/ddd/',
// or send a mail to the DDD developers <ddd@gnu.org>.

#include "my-alloca.h"

// Yes, alloca() must come even before this simple stuff.  Sigh.
char VSLRead_rcsid[] = 
    "$Id$";

#include <stdlib.h>
#include <limits.h>
#include <iostream>
#include <fstream>
#include <sstream>

#include "assert.h"
#include "strclass.h"
#include "cook.h"

#include "VSLBuiltin.h"

#include "VSLLib.h"
#include "VSLDef.h"
#include "VSLDefList.h"

#include "Box.h"
#include "PrimitiveB.h"
#include "StringBox.h"
#include "TrueBox.h"
#include "ListBox.h"

#include "VSLNode.h"
#include "ConstNode.h"
#include "ListNode.h"
#include "TestNode.h"
#include "DefCallN.h"
#include "LetNode.h"
#include "ArgNode.h"
#include "DummyNode.h"
#include "NameNode.h"
#include "TrueNode.h"

#include "VSEFlags.h"
#include "config.h"


static VSLLib *vsllib = 0;	// The VSL library to read

static string vslfilename = "standard input";   // Current file name

// Some type decls for $$
struct VSLFunctionHeader {
    string *id;
    VSLNode *pattern;
    string *file;
    int line;
};

struct VSLVarDefinition {
    VSLNode *pattern;
    VSLNode *args;
};

// GNU C++ complains about the declaration of VSLSTYPE, so leave it alone
#ifdef __GNUG__
#define VSLSTYPE _xy_VSLSTYPE
#define _VSLSTYPE _xy_underscore_VSLSTYPE
#define vsllval  _xy_vsllval
#include "vsl-gramma.h"
#undef vsllval
#undef _VSLSTYPE
#undef VSLSTYPE
#else
#include "vsl-gramma.h"
#endif

#define ASSERT(ignore)

// Set this to enable assertions while parsing
// #undef ASSERT
// #define ASSERT(x) assert(x)

// The parse function generated by YACC -- this cannot be a C++ name
#define vslparse VSLLib_parse

#include "vsl-lex.C"
#include "vsl-gramma.C"

#undef vslparse

// Read library

// Update library from stream
void VSLLib::update(std::istream& s)
{
    vsllib = this;

    vslstream = &s;
    if (vslfilename.empty())
	vslfilename = _lib_name;

    // Read it
    vslnameSet.reset();
    pushback_ptr = pushback;
    parse();

    if (VSEFlags::verbose)
    {
	std::cout << ")";
	std::cout.flush();
    }

    if (VSEFlags::verbose)
	std::cout << ", done.\n";

    // Reset name and file number
    vsllinenumber = 0;
    vslfilename   = "";
}


// Update library from file
void VSLLib::update(const string& lib_name)
{
    if (VSEFlags::verbose)
    {
	if (lib_name.empty())
	    std::cout << "standard input";
	else
	    std::cout << lib_name;
	std::cout << ": reading";
	std::cout.flush();
    }

    vslfilename = lib_name;

    switchreset();
    if (switchup(lib_name.chars(), true) == 0)
    {
	assert(vslstream != 0);

	topstack = 0;
	update(*vslstream);
    }
}


// Error handling

// Yacc-specific error handling
void vslerror(const char *s)
{
    string errmsg = s;

    if (errmsg == "syntax error" || errmsg == "parse error")
	 errmsg += " near " + quote((char *)vsltext);

    VSLLib::parse_error(errmsg);
}

// Parsing message
void VSLLib::parse_echo(const string& msg)
{
    std::ostringstream os;

    if (vsllinenumber > 0)
	os << vslfilename << ":" << vsllinenumber << ": ";
    os << msg;
    echo(os);
}

// Parsing error
void VSLLib::parse_error(const string& errmsg)
{
    parse_echo(errmsg);
}

// Parsing warning
void VSLLib::parse_warning(const string& errmsg)
{
    parse_echo("warning: " + errmsg);
}
