/***** Autogenerated from runsystem.in; changes will be overwritten *****/

#line 1 "runtimebase.in"
/*****
 * runtimebase.in
 * Andy Hammerlindl  2009/07/28
 *
 * Common declarations needed for all code-generating .in files.
 *
 *****/


#line 1 "runsystem.in"
/*****
 * runsystem.in
 *
 * Runtime functions for system operations.
 *
 *****/

#line 1 "runtimebase.in"
#include "stack.h"
#include "types.h"
#include "builtin.h"
#include "entry.h"
#include "errormsg.h"
#include "array.h"
#include "triple.h"
#include "callable.h"

using vm::stack;
using vm::error;
using vm::array;
using vm::callable;
using types::formal;
using types::function;
using camp::triple;

#define PRIMITIVE(name,Name,asyName) using types::prim##Name;
#include <primitives.h>
#undef PRIMITIVE

typedef double real;

void unused(void *);

namespace run {
array *copyArray(array *a);
array *copyArray2(array *a);
array *copyArray3(array *a);

double *copyArrayC(const array *a, size_t dim=0);
double *copyArray2C(const array *a, bool square=true, size_t dim2=0);

triple *copyTripleArrayC(const array *a, size_t dim=0);
triple *copyTripleArray2C(const array *a, bool square=true, size_t dim2=0);
double *copyTripleArray2Components(array *a, bool square=true, size_t dim2=0);
}

function *realRealFunction();

#define CURRENTPEN processData().currentpen

#line 12 "runsystem.in"
#include "process.h"
#include "stack.h"
#include "locate.h"

using namespace camp;
using namespace settings;
using vm::bpinfo;
using vm::bplist;
using vm::getPos;
using vm::default_t;
using vm::nullfunc;
using vm::item;
using absyntax::runnable;

typedef callable callableBp;

namespace run {
extern default_t def;
extern string emptystring;
}

function *voidFunction()
{
  return new function(primVoid());
}

function *breakpointFunction()
{
  return new function(primString(),primString(),primInt(),primInt(),
                      primCode());
}

void clear(string file, Int line, bool warn=false) 
{
  bpinfo bp(file,line);
  for(mem::list<bpinfo>::iterator p=bplist.begin(); p != bplist.end(); ++p) {
    if(*p == bp) {
      cout << "cleared breakpoint at " << file << ": " << line << endl;
      bplist.remove(bp);
      return;
    }
  }
  if(warn)
    cout << "No such breakpoint at "  << file << ": " << line << endl;
}

namespace run {
void breakpoint(stack *Stack, runnable *r)
{
  callable *atBreakpointFunction=processData().atBreakpointFunction;
  if(atBreakpointFunction &&
     !nullfunc::instance()->compare(atBreakpointFunction)) {
    position curPos=getPos();
    Stack->push<string>(curPos.filename());
    Stack->push<Int>((Int) curPos.Line());
    Stack->push<Int>((Int) curPos.Column());
    Stack->push(r ? r : item(run::def));
    atBreakpointFunction->call(Stack); // returns a string
  } else Stack->push<string>("");
}
}

string convertname(string name, const string& format, bool check=true)
{
  if(name.empty())
    return buildname(outname(),format,"");
  else
    if(check) checkLocal(name);
  return format.empty() ? name : format+":"+name;
}

namespace run {
void purge(Int divisor=0)
{
#ifdef USEGC
  if(divisor > 0) GC_set_free_space_divisor((GC_word) divisor);
  GC_gcollect();
#endif
}

void updateFunction(stack *Stack)
{
  callable *atUpdateFunction=processData().atUpdateFunction;
  if(atUpdateFunction && !nullfunc::instance()->compare(atUpdateFunction))
    atUpdateFunction->call(Stack);
}

void exitFunction(stack *Stack)
{
  callable *atExitFunction=processData().atExitFunction;
  if(atExitFunction && !nullfunc::instance()->compare(atExitFunction))
    atExitFunction->call(Stack);
}
}

// Autogenerated routines:


namespace run {
#line 109 "runsystem.in"
// void atupdate(callable *f);
void gen_runsystem0(stack *Stack)
{
  callable * f=vm::pop<callable *>(Stack);
#line 110 "runsystem.in"
  processData().atUpdateFunction=f;
}

#line 114 "runsystem.in"
// callable* atupdate();
void gen_runsystem1(stack *Stack)
{
#line 115 "runsystem.in"
  {Stack->push<callable*>(processData().atUpdateFunction); return;}
}

#line 119 "runsystem.in"
// void atexit(callable *f);
void gen_runsystem2(stack *Stack)
{
  callable * f=vm::pop<callable *>(Stack);
#line 120 "runsystem.in"
  processData().atExitFunction=f;
}

#line 124 "runsystem.in"
// callable* atexit();
void gen_runsystem3(stack *Stack)
{
#line 125 "runsystem.in"
  {Stack->push<callable*>(processData().atExitFunction); return;}
}

#line 129 "runsystem.in"
// void atbreakpoint(callableBp *f);
void gen_runsystem4(stack *Stack)
{
  callableBp * f=vm::pop<callableBp *>(Stack);
#line 130 "runsystem.in"
  processData().atBreakpointFunction=f;
}

#line 134 "runsystem.in"
// void breakpoint(runnable *s=NULL);
void gen_runsystem5(stack *Stack)
{
  runnable * s=vm::pop<runnable *>(Stack,NULL);
#line 135 "runsystem.in"
  breakpoint(Stack,s);
}

#line 139 "runsystem.in"
// string locatefile(string file);
void gen_runsystem6(stack *Stack)
{
  string file=vm::pop<string>(Stack);
#line 140 "runsystem.in"
  {Stack->push<string>(locateFile(file)); return;}
}

#line 144 "runsystem.in"
// void stop(string file, Int line, runnable *s=NULL);
void gen_runsystem7(stack *Stack)
{
  runnable * s=vm::pop<runnable *>(Stack,NULL);
  Int line=vm::pop<Int>(Stack);
  string file=vm::pop<string>(Stack);
#line 145 "runsystem.in"
  file=locateFile(file);
  clear(file,line);
  cout << "setting breakpoint at " << file << ": " << line << endl;
  bplist.push_back(bpinfo(file,line,s));
}

#line 152 "runsystem.in"
// void breakpoints();
void gen_runsystem8(stack *)
{
#line 153 "runsystem.in"
  for(mem::list<bpinfo>::iterator p=bplist.begin(); p != bplist.end(); ++p)
    cout << p->f.name() << ": " << p->f.line() << endl;
}

#line 158 "runsystem.in"
// void clear(string file, Int line);
void gen_runsystem9(stack *Stack)
{
  Int line=vm::pop<Int>(Stack);
  string file=vm::pop<string>(Stack);
#line 159 "runsystem.in"
  file=locateFile(file);
  clear(file,line,true);
}

#line 164 "runsystem.in"
// void clear();
void gen_runsystem10(stack *)
{
#line 165 "runsystem.in"
  bplist.clear();
}

#line 169 "runsystem.in"
// void warn(string s);
void gen_runsystem11(stack *Stack)
{
  string s=vm::pop<string>(Stack);
#line 170 "runsystem.in"
  Warn(s);
}

#line 174 "runsystem.in"
// void nowarn(string s);
void gen_runsystem12(stack *Stack)
{
  string s=vm::pop<string>(Stack);
#line 175 "runsystem.in"
  noWarn(s);
}

#line 179 "runsystem.in"
// void warning(string s, string t, bool position=false);
void gen_runsystem13(stack *Stack)
{
  bool position=vm::pop<bool>(Stack,false);
  string t=vm::pop<string>(Stack);
  string s=vm::pop<string>(Stack);
#line 180 "runsystem.in"
  if(settings::warn(s)) {
    em.warning(position ? getPos() : nullPos,s);
    em << t;
  }
}

// Strip directory from string
#line 188 "runsystem.in"
// string stripdirectory(string *s);
void gen_runsystem14(stack *Stack)
{
  string * s=vm::pop<string *>(Stack);
#line 189 "runsystem.in"
  {Stack->push<string>(stripDir(*s)); return;}
}

// Strip directory from string
#line 194 "runsystem.in"
// string stripfile(string *s);
void gen_runsystem15(stack *Stack)
{
  string * s=vm::pop<string *>(Stack);
#line 195 "runsystem.in"
  {Stack->push<string>(stripFile(*s)); return;}
}

// Strip file extension from string
#line 200 "runsystem.in"
// string stripextension(string *s);
void gen_runsystem16(stack *Stack)
{
  string * s=vm::pop<string *>(Stack);
#line 201 "runsystem.in"
  {Stack->push<string>(stripExt(*s)); return;}
}

// Call ImageMagick convert.
#line 206 "runsystem.in"
// Int convert(string args=emptystring, string file=emptystring,            string format=emptystring);
void gen_runsystem17(stack *Stack)
{
  string format=vm::pop<string>(Stack,emptystring);
  string file=vm::pop<string>(Stack,emptystring);
  string args=vm::pop<string>(Stack,emptystring);
#line 208 "runsystem.in"
  string name=convertname(file,format);
  mem::vector<string> cmd;
  cmd.push_back(getSetting<string>("convert"));
  push_split(cmd,args);
  cmd.push_back(name);
  bool quiet=verbose <= 1;
  Int ret=System(cmd,quiet ? 1 : 0,true,"convert",
                 "your ImageMagick convert utility");
  
  if(ret == 0 && verbose > 0)
    cout << "Wrote " << ((file.empty()) ? name : file) << endl;
  
  {Stack->push<Int>(ret); return;}
}

// Call ImageMagick animate.
#line 225 "runsystem.in"
// Int animate(string args=emptystring, string file=emptystring,            string format=emptystring);
void gen_runsystem18(stack *Stack)
{
  string format=vm::pop<string>(Stack,emptystring);
  string file=vm::pop<string>(Stack,emptystring);
  string args=vm::pop<string>(Stack,emptystring);
#line 227 "runsystem.in"
#ifndef __CYGWIN__
  string name=convertname(file,format,false);
  if(view()) {
    mem::vector<string> cmd;
    cmd.push_back(getSetting<string>("animate"));
    push_split(cmd,args);
    cmd.push_back(name);
    {Stack->push<Int>(System(cmd,0,false,"animate","your animated GIF viewer")); return;}
  }
#endif  
  {Stack->push<Int>(0); return;}
}

#line 241 "runsystem.in"
// void purge(Int divisor=0);
void gen_runsystem19(stack *Stack)
{
  Int divisor=vm::pop<Int>(Stack,0);
#line 242 "runsystem.in"
  purge(divisor);
}

} // namespace run

namespace trans {

void gen_runsystem_venv(venv &ve)
{
#line 109 "runsystem.in"
  addFunc(ve, run::gen_runsystem0, primVoid(), "atupdate", formal(voidFunction(), "f", false, false));
#line 114 "runsystem.in"
  addFunc(ve, run::gen_runsystem1, voidFunction(), "atupdate");
#line 119 "runsystem.in"
  addFunc(ve, run::gen_runsystem2, primVoid(), "atexit", formal(voidFunction(), "f", false, false));
#line 124 "runsystem.in"
  addFunc(ve, run::gen_runsystem3, voidFunction(), "atexit");
#line 129 "runsystem.in"
  addFunc(ve, run::gen_runsystem4, primVoid(), "atbreakpoint", formal(breakpointFunction(), "f", false, false));
#line 134 "runsystem.in"
  addFunc(ve, run::gen_runsystem5, primVoid(), "breakpoint", formal(primCode(), "s", true, false));
#line 139 "runsystem.in"
  addFunc(ve, run::gen_runsystem6, primString() , "locatefile", formal(primString() , "file", false, false));
#line 144 "runsystem.in"
  addFunc(ve, run::gen_runsystem7, primVoid(), "stop", formal(primString() , "file", false, false), formal(primInt(), "line", false, false), formal(primCode(), "s", true, false));
#line 152 "runsystem.in"
  addFunc(ve, run::gen_runsystem8, primVoid(), "breakpoints");
#line 158 "runsystem.in"
  addFunc(ve, run::gen_runsystem9, primVoid(), "clear", formal(primString() , "file", false, false), formal(primInt(), "line", false, false));
#line 164 "runsystem.in"
  addFunc(ve, run::gen_runsystem10, primVoid(), "clear");
#line 169 "runsystem.in"
  addFunc(ve, run::gen_runsystem11, primVoid(), "warn", formal(primString() , "s", false, false));
#line 174 "runsystem.in"
  addFunc(ve, run::gen_runsystem12, primVoid(), "nowarn", formal(primString() , "s", false, false));
#line 179 "runsystem.in"
  addFunc(ve, run::gen_runsystem13, primVoid(), "warning", formal(primString() , "s", false, false), formal(primString() , "t", false, false), formal(primBoolean(), "position", true, false));
#line 187 "runsystem.in"
  addFunc(ve, run::gen_runsystem14, primString() , "stripdirectory", formal(primString(), "s", false, false));
#line 193 "runsystem.in"
  addFunc(ve, run::gen_runsystem15, primString() , "stripfile", formal(primString(), "s", false, false));
#line 199 "runsystem.in"
  addFunc(ve, run::gen_runsystem16, primString() , "stripextension", formal(primString(), "s", false, false));
#line 205 "runsystem.in"
  addFunc(ve, run::gen_runsystem17, primInt(), "convert", formal(primString() , "args", true, false), formal(primString() , "file", true, false), formal(primString() , "format", true, false));
#line 224 "runsystem.in"
  addFunc(ve, run::gen_runsystem18, primInt(), "animate", formal(primString() , "args", true, false), formal(primString() , "file", true, false), formal(primString() , "format", true, false));
#line 241 "runsystem.in"
  addFunc(ve, run::gen_runsystem19, primVoid(), "purge", formal(primInt(), "divisor", true, false));
}

} // namespace trans
