Logo Search packages:      
Sourcecode: kaya version File versions  Download package

stdfuns.cc

/**
    Kaya run-time system
    Copyright (C) 2004, 2005 Edwin Brady

    This file is distributed under the terms of the GNU Lesser General
    Public Licence. See COPYING for licence.
*/

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h> 
#include <sys/resource.h> 
#include <unistd.h>
#include <vector>
#include <malloc.h>

#include <pthread.h>
#define GC_PTHREADS
#include <gc/gc.h>

#include "stdfuns.h"
#include "Heap.h"
#include "Closure.h"
#include "VM.h"
#include "VMState.h"
#include "KayaAPI.h"

KayaArray args;
ArgMap httpargs;

char* inttostr(int s, int base)
{
    char* buf=(char*)GC_MALLOC(255*sizeof(char));
    switch(base) {
    case 10:
      sprintf(buf,"%d",s);
      break;
    case 16:
      sprintf(buf,"%x",s);
      break;
    case 8:
      sprintf(buf,"%o",s);
      break;
    default:
      sprintf(buf,"%d",s); // Can't do weird bases yet.
      break;
    }
    return buf;
}

int strtoint(char* str, int base)
{
    return strtol(str,NULL,base);
}

char* getsubstr(char* x,int i,int len)
{
//    int max = strlen(x);
    char* n = (char*)GC_MALLOC((len+1)*sizeof(char));
    strncpy(n,x+i,len);
/*    for(int j=0;j<len && (j+i)<max;j++) {
      n[j] = x[j+i];
    }
    n[len]='\0';*/
    return n;
}

char* getstrend(char* x,int i)
{
    int max = strlen(x);
    char* n = (char*)GC_MALLOC((max+1-i)*sizeof(char));
    strcpy(n,x+i);
/*    for(int j=0;j<len && (j+i)<max;j++) {
      n[j] = x[j+i];
    }
    n[len]='\0';*/
    return n;
}

char* readstr()
{
    char* buf=(char*)GC_MALLOC(255*sizeof(char));
    fgets(buf,255,stdin);
    char *loc = strchr(buf,'\n');
    *loc = '\0';
    return buf;
}

unsigned char getIndex(char* str,int i)
{
    return (unsigned char)(str[i]);
}

char* getLine(FILE* f)
{
// I know there's a better way. Can't be bothered.
    char* buf=(char*)GC_MALLOC_ATOMIC(4096*sizeof(char)); 
    fgets(buf,4096,f);
    return buf;    
}

void putLine(FILE* f, char* c)
{
    fputs(c,f);
}

void printArray(KayaArray foo)
{
    for(int i=0;i<foo->size();i++) {
      cout << foo->lookup(i)->getString()->getVal() << endl;
    }
}

KayaArray reverseArray(KayaArray foo)
{
    KayaArray bar = new Array();
    for(unsigned i=foo->size();i>0;i--) {
      bar->push_back(foo->lookup(i-1));
    }
    return bar;
}

void shortenArray(KayaArray foo)
{
    if (foo->size()>0) {
      foo->resize(foo->size()-1);
    }
}

KayaValue shiftArray(KayaArray foo)
{
    return foo->shift();
}

KayaArray createArray(int size)
{
    return newKayaArray(size);
}

void resizeArray(KayaArray foo, int size)
{
    foo->resize(size);
}

int arraySize(KayaArray foo)
{
    return foo->size();
}


FILE* getstdin()
{
    return stdin;
}

FILE* getstdout()
{
    return stdout;
}

FILE* getstderr()
{
    return stderr;
}

void setStdErr(FILE* f)
{
    stderr = f;
}

bool validFile(FILE* f)
{
    return f!=NULL;
}

void storeArgs(int argc,char* argv[])
{
    args = new Array();
    for (int i=0;i<argc;i++) {
      KayaValue arg = new Value((void*)(new String(argv[i])),stringtable);
      args->push_back(arg);
    }
}

KayaArray getArgs()
{
    return args;
}

int gettime()
{
    return (int)(time(NULL));
}

KayaValue dogmtime(int secs)
{
    Union* tu = new Union(NULL,0,9,false);
    struct tm ts;
    time_t t = (time_t)secs;
    gmtime_r(&t,&ts);
    Union* mon = new Union(NULL,ts.tm_mon,0,false);
    Union* wday = new Union(NULL,ts.tm_wday,0,false);

    tu->args[0]=MKINT(ts.tm_sec);
    tu->args[1]=MKINT(ts.tm_min);
    tu->args[2]=MKINT(ts.tm_hour);
    tu->args[3]=MKINT(ts.tm_mday);
    tu->args[4]=MKUNION(mon);
    tu->args[5]=MKINT((ts.tm_year+1900));
    tu->args[6]=MKUNION(wday);
    tu->args[7]=MKINT(ts.tm_yday);
    tu->args[8]=MKINT(ts.tm_isdst);
    return new Value((void*)tu,uniontable);
}

KayaValue dolocaltime(int secs)
{
    Union* tu = new Union(NULL,0,9,false);
    struct tm ts;
    time_t t = (time_t)secs;
    localtime_r(&t,&ts);
    Union* mon = new Union(NULL,ts.tm_mon,0,false);
    Union* wday = new Union(NULL,ts.tm_wday,0,false);

    tu->args[0]=MKINT(ts.tm_sec);
    tu->args[1]=MKINT(ts.tm_min);
    tu->args[2]=MKINT(ts.tm_hour);
    tu->args[3]=MKINT(ts.tm_mday);
    tu->args[4]=MKUNION(mon);
    tu->args[5]=MKINT((ts.tm_year+1900));
    tu->args[6]=MKUNION(wday);
    tu->args[7]=MKINT(ts.tm_yday);
    tu->args[8]=MKINT(ts.tm_isdst);
    return new Value((void*)tu,uniontable);
}

int domktime(KayaValue time)
{
    struct tm t;
    Union* tu = time->getUnion();
    t.tm_sec = tu->args[0]->getInt();
    t.tm_min = tu->args[1]->getInt();
    t.tm_hour = tu->args[2]->getInt();
    t.tm_mday = tu->args[3]->getInt();
    t.tm_year = (tu->args[5]->getInt())-1900;
    t.tm_yday = tu->args[7]->getInt();
    t.tm_isdst = tu->args[8]->getInt();
    t.tm_mon = tu->args[4]->getUnion()->tag;
    t.tm_wday = tu->args[6]->getUnion()->tag;

    int x = (int)mktime(&t);
    return x;
}

int getclock()
{
    return (int)(clock());
}

int runProgram(char* prog, KayaArray args)
{
    char** argv = new char*[args->size()+2];

    argv[0]=prog;
    for(int i=0;i<args->size();i++) {
      argv[i+1]=args->lookup(i)->getString()->getVal();
    }
    argv[args->size()+1]=NULL;
    pid_t pid = fork();
    int status;
    if (pid==0) {
      execvp(prog,argv);
      exit(0);
    }
    else {
      wait(&status);
    }

    delete argv;
    return status;
}

int dofork()
{
    return (int)fork();
}

void reap()
{
    waitpid(-1,NULL,WNOHANG);
}

int dowait()
{
    int status;
    wait(&status);
    return status;
}

int dowaitpid(int pid)
{
    int status;
    waitpid(pid,&status,0);
    return status;
}

/** The following base64 functions are adapted from
 * http://base64.sourceforge.net/b64.c
 * By Bob Trower, Copyright (c) Trantor Standard Systems Inc., 2001
 */

/*
** Translation Table as described in RFC1113
*/
static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/*
** Translation Table to decode (created by author)
*/
static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";

/*
** encodeblock
**
** encode 3 8-bit binary bytes as 4 '6-bit' characters
*/
void encodeblock( unsigned char in[3], unsigned char out[4], int len )
{
    out[0] = cb64[ in[0] >> 2 ];
    out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
    out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
    out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}

/*
** decodeblock
**
** decode 4 '6-bit' characters into 3 8-bit binary bytes
*/
void decodeblock( unsigned char in[4], unsigned char out[3] )
{   
    out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
    out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
    out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
}

char* b64enc(char* block, int len)
{
    char* outblock = (char*)GC_malloc(sizeof(char)*len*2);
    unsigned char in[3], out[4];
    int i,x,y;
    x=0; // Input pointer
    y=0; // Output pointer
    while(x<len) {
      for(i = 0; i<3;i++) {
          if (x>=len) { 
            in[i]=0;
          } else {
            unsigned char v = (unsigned char)block[x];
            in[i]=v;
          }
          x++;
      }
      encodeblock(in,out,3);
      for(i=0;i<4;i++) {
          outblock[y] = out[i];
          y++;
      }
    }
    outblock[y]='\0';
    return outblock;
}

char* b64dec(char* block, KayaValue outlen)
{
    int len = strlen(block);
    char* outblock = (char*)GC_malloc(sizeof(char)*len);
    unsigned char in[4], out[3];
    int i,x,y;
    x=0; // Input pointer
    y=0; // Output pointer
    while(x<len) {
      for(i = 0; i<4;i++) {
          if (x>=len) { 
            in[i]=0;
          } else {
            unsigned char v = (unsigned char)block[x];
            v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
                if( v ) {
                    v = (unsigned char) ((v == '$') ? 0 : v - 61);
                }
            in[i]=v-1;
          }
          x++;
      }
      decodeblock(in,out);
      for(i=0;i<3;i++) {
          outblock[y] = out[i];
          y++;
      }
    }
    outblock[y]='\0';
    KayaSetInt(outlen,y-1);
    return outblock;
}

/** End of Bob Trower's code */

/*
int funtable_compare(KayaValuex, KayaValue y)
{
    return x->getFunTable()->cmp(x,y)->getInt();
}
*/

void qs(VMState* vm, KayaArray xs,int l, int r,Closure* f);
int partition(VMState* vm, KayaArray xs, int l, int r, int pi, Closure* sortfn);

void quicksort(KayaArray xs, KayaValue sortfn)
{
// Don't need the real VM (but maybe it'd be quicker)
    static VMState* vm = new VMState(); 
    Closure* f = sortfn->getFunc();
    qs(vm,xs,0,xs->size()-1,f);
}

void qs(VMState* vm,KayaArray xs,int l, int r,Closure* f)
{
    if (r>l) {
      int pi = partition(vm,xs,l,r,(l+r)/2,f);
      qs(vm,xs,l,pi-1,f);
      qs(vm,xs,pi+1,r,f);
    }
}

int partition(VMState* vm, KayaArray xs, int l, int r, int pi, Closure* sortfn)
{
    KayaValue xpi = xs->lookup(pi);
    static KayaValue pivotval = new Value(NULL,inttable);
    static KayaValue tmp = new Value(NULL,inttable);
    pivotval->setPtr(xpi);
//    swap(xpi,xs->lookup(r));

    tmp->setPtr(xs->lookup(r));
    xs->lookup(r)->setPtr(xpi);
    xpi->setPtr(tmp);

/*    cout << "Before Partition " << l << " - " << r << " : ";
    for(unsigned i=0;i<xs->size();i++) {
      cout << xs->lookup(i)->getInt() << ",";
    }
    cout << endl;*/

    int si = l;
    for(int i=l; i<r; i++) {
      vm->push(pivotval);
      vm->push(xs->lookup(i));
      sortfn->run(vm);
      int res = vm->doPop()->getInt();
      if (res<0) {
          tmp->setPtr(xs->lookup(si));
          xs->lookup(si)->setPtr(xs->lookup(i));
          xs->lookup(i)->setPtr(tmp);
//        swap(xs->lookup(si),xs->lookup(i));
          si++;
      }
    }
//    swap(xs->lookup(r),xs->lookup(si));
    tmp->setPtr(xs->lookup(r));
    xs->lookup(r)->setPtr(xs->lookup(si));
    xs->lookup(si)->setPtr(tmp);

/*    cout << "Partition: ";
    for(unsigned i=0;i<xs->size();i++) {
      cout << xs->lookup(i)->getInt() << ",";
    }
    cout << endl;*/
    return si;
}

bool funtable_eq(KayaValue x, KayaValue y)
{
    return x->getFunTable()->eq(x,y)->getInt();
}

int funtable_hash(KayaValue x)
{
    return x->getFunTable()->hash(x)->getInt();
}

char* funtable_marshal(void* vmptr,KayaValue x, int i)
{
    VMState* vm = (VMState*)vmptr;
    vector<KayaValue> done;
    return x->getFunTable()->marshal(vm,done,x,i)->getString()->getVal();
}

char* funtable_marshal_aux(void* vmptr,vector<KayaValue>& done,KayaValue x, int i)
{
    VMState* vm = (VMState*)vmptr;
    return x->getFunTable()->marshal(vm,done,x,i)->getString()->getVal();
}

KayaValue funtable_copy(KayaValue x)
{
    return x->getFunTable()->copy(x);
}

KayaValue unsafe_id(KayaValue x)
{
    return x;
}

char* getAddr(KayaValue x)
{
    char* buf=(char*)GC_MALLOC(65536*sizeof(char)); 
    sprintf(buf,"Address of value at %p is %p",x,x->getRaw());
    return buf;
}

char* except_msg(KayaValue x)
{
    return x->getExcept()->err->getVal();
}

int except_code(KayaValue x)
{
    return x->getExcept()->code;
}

int doGetFnID(KayaValue fn)
{
    return getFnID(fn->getFunc()->getfn());
}

void callFnID(void* vmptr, int id, KayaValue arg)
{
    VMState* vm = (VMState*)vmptr;
    func f = getFn(id);
    if (f!=NULL) {
      PUSH(arg);
      f(vm);
    } else {
      vm->kaya_throw("Illegal function id",1);
    }
}

int memusage()
{
/*    struct rusage usage;
    int x = getrusage(RUSAGE_SELF,&usage);
    if (x!=0) return -1;
    int total = usage.ru_idrss+usage.ru_isrss+usage.ru_maxrss;
    return total; */
    struct mallinfo info = mallinfo();

    return info.arena;
}

int isNull(void* p)
{
    return p==NULL;
}

/* Code to handle do_access() in IO.k 
// Added by Chris Morris, 18/6/05 */
int do_access(char* pathname, KayaValue mode) {
  int tag = KayaUnionGetTag(mode);
  int acmode = 0;
  switch(tag) {
  case 0:
    acmode = F_OK;
    break;
  case 1:
    acmode = X_OK;
    break;
  case 2:
    acmode = W_OK;
    break;
  case 3:
    acmode = R_OK;
    break;
  }
  return access(pathname,acmode);

}

int getres(KayaValue lim, bool& ok)
{
    ok = true;
    switch(KayaUnionGetTag(lim)) {
    case 0:
      return RLIMIT_AS;
      break;
    case 1:
      return RLIMIT_CORE;
      break;
    case 2:
      return RLIMIT_CPU;
      break;
    case 3:
      return RLIMIT_DATA;
      break;
    case 4:
      return RLIMIT_FSIZE;
      break;
    case 5:
#ifdef RLIMIT_LOCKS
      return RLIMIT_LOCKS;
#else
      ok = false;
      return 0;
#endif
      break;
    case 6:
#ifdef RLIMIT_MEMLOCK
      return RLIMIT_MEMLOCK;
#else
      ok = false;
      return 0;
#endif
      break;
    case 7:
      return RLIMIT_NOFILE;
      break;
    case 8:
#ifdef RLIMIT_NPROC
      return RLIMIT_NPROC;
#else
      ok = false;
      return 0;
#endif
      break;
    case 9:
#ifdef RLIMIT_RSS
      return RLIMIT_RSS;
#else
      ok = false;
      return 0;
#endif
      break;
    case 10:
      return RLIMIT_STACK;
      break;
    default:
      return RLIMIT_AS; // Can't happen anyway
    }
}

int do_setrlimit(KayaValue lim, int soft, int hard)
{
    struct rlimit r;
    if (soft==-1) {
      r.rlim_cur = RLIM_INFINITY;
    } else {
      r.rlim_cur=soft;
    }
    if (soft==-1) {
      r.rlim_max=RLIM_INFINITY;
    } else {
      r.rlim_max=hard;
    }
    bool ok;
    int res = getres(lim,ok);
    if (ok) {
      setrlimit(res,&r);
      return 1;
    } else {
      return 0;
    }
}


Generated by  Doxygen 1.6.0   Back to index