#include <strstream.h>
// #include <Integer.h>
// #include <Obstack.h>
#include "types.h"
#include "newtype.h"
#include "gennum.h"
#include "gvars.h"
#include "genmap.h"
#include "gassign.h"
#include "gfunc.h"
#include "exceptions.h"
//#include "hash.h"
#include <stddef.h>
#include <std.h>
#include "evalprocs.h"
#include "shell.h"
#include "gfiles.h"
#include <typetabs.h>

#if 0
static struct Any IntTmpToAny(IntRep *I)
{
    if (Iislong(I)) {
	long i = Itolong(I);
	delete I;
	return LongToAny(i);
    } else {
	return MAKE_ANY(I, BigNumT);
    }
}

#endif

#if 0
void PrintNumeric(struct Any self, FILE *file)
{ ((Numeric*)self.addr)->printon(file); }

struct Any BigNumPlus(struct Any a, struct Any b)
{
    if (b.type == FixNumT || b.type == IntT) {
	IntRep *I = add((IntRep*)a.addr, 0, (long)b.addr, 0);
	return IntTmpToAny(I);
    }
    else if (b.type == BigNumT) {
	IntRep *I = add((IntRep*)a.addr, 0, (IntRep*)b.addr, 0, 0);
	return IntTmpToAny(I);
    }
    else RaiseDomainError(sPlus);
}

void BigNumPrint(struct Any big, FILE *f)
{
//    fputs(Itoa((IntRep*)big.addr), f);
}
#endif

extern "C" Double *AllocDouble(double val);
Double *AllocDouble(double val)
{ return new Double(val); }

int VLong(Root *val, long *i)
{
    const Numeric *num = val->numeric();
    if (num == NULL) return 0;
    return num->getlong(i);
}

int VCompare(Root *val, Root *other) { return val->compare(*other); }
void VUnify(Root *val, Root *other) { val->unify(*other); }

#if 0
/* Enlarge STREAM's buffer.  */
void
enlarge_buffer(register FILE *stream, int flush_only, int c)
{
  ptrdiff_t bufp_offset = stream->__bufp - stream->__buffer;

  stream->__bufsize += 100;
  stream->__buffer = (char *) realloc(stream->__buffer,stream-> __bufsize);
  if (stream->__buffer == NULL)
      stream->__bufp = stream->__put_limit = NULL;
  else
    {
      stream->__bufp = stream->__buffer + bufp_offset;
      stream->__put_limit = stream->__buffer + stream->__bufsize;
      if (!flush_only)
	*stream->__bufp++ = (unsigned char) c;
    }
}
#endif

void VString(Root *val, char **str, size_t *lenp)
{
    long save_print_readable = print_readable;
    print_readable = 0;
    ostrstream outs;
    outs << *val;
    if (lenp)
	*lenp = outs.pcount();
    outs << ends;
    *str = outs.str();
    print_readable = save_print_readable;
}

unsigned VLength(Root *val)
{
    GenMap *m = val->mapping();
    if (m == NULL) RaiseDomainError(0);
    return m->length();
}

Root * VSubSeq(Root *inseq, int first, unsigned length)
{
    GenSeq * q = inseq->sequence();
    if (q == NULL) return NULL;
    return q->subseq(first, first+length);
}

Root *LookupSpecial(Symbol * name)
{   Root *val;
    char *str;
#if 0
    extern HashTable *SpecialVars;
    val = SearchSpecial(name);
    if (val != NULL) return val;
#endif
    val = name->sym_value();
    if (val != NULL)
	return val;
    val = name->sym_function();
    if (val != NULL)
	return val;
    str = getenv(SymbolString(name));
    if (str) {
	return new String(str, strlen(str));
    }
#if 0
    if (access(name->string(), 0) == 0)
	return new FileNode(name->Str());
#endif
    fprintf(stderr, "[Unbound special variable: %s]\n", name->string());
    val = AllocVariable(name);
#if 1
    name->sym_value(val);
#else
    Insert(SpecialVars, name, val);
#endif
    return val;
}
