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

sial_builtin.c

/*
 * Copyright 2001 Silicon Graphics, Inc. All rights reserved.
 */
#include <string.h>
#include <termio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "sial.h"

/* information necessary for a builtin function */
typedef struct builtin {

      var_t*v;          /* resulting variable declaration after parsing */
        bf_t *fp;       /* pointer to actual function */
      char *proto;            /* associated prototype_t*/
      struct builtin *next;   /* to chain them */

} builtin;

#define BT_EINVAL 1     /* Something is wrong and it's not ... */
value_t*
sial_exit(int v)
{
      /* Were we compiling ? */
      sial_parseback();

      /* we were running... exit () */
      sial_dojmp(J_EXIT, &v);

      /* NOT REACHED */
      return 0;
}

value_t*
sial_bexit(value_t *vv)
{
int v=sial_getval(vv);

      /* we're not going back to the he caller so free 
         the input value_t */
      sial_freeval(vv);
      sial_exit(v);
      /* NOT REACHED */
      return 0;
}

#define MAXBYTES  4000
#define INCREMENT 16
value_t *
sial_getstr(value_t *vmadr)
{
ull madr=sial_getval(vmadr);
char *buf=sial_alloc(MAXBYTES+1);
char *p=buf;
value_t *v;

      /* sial as already verified that this is a V_REF */
      /* since this is reading from a unkown size pool
         we have to do an exponential reduction on the number of bytes
         read ... */
      buf[0]=0;
      while(1) {

            int i;

            if(!API_GETMEM(madr, p, INCREMENT)) break;

            /* have we found the '\0' yet ? */
            for(i=0;i<INCREMENT; i++) if(!p[i]) break;

            madr+=INCREMENT;
            p+=INCREMENT;
            if((p-buf) >= MAXBYTES) {
                  buf[MAXBYTES]='\0';
                  break;
            }

      }
      v=sial_setstrval(sial_newval(), buf);
      sial_free(buf);
      return v;
}

value_t *
sial_substr(value_t *vp, value_t *vi, value_t *vj)
{
char *p=sial_getptr(vp, char); 
ul i=sial_getval(vi); 
int l=strlen(p);
int j=(vj?sial_getval(vj):(l-i+1));
char *s;
value_t *v;

      if((i+j-1)>l || !i) {

            sial_error("Valid positions are [1..%d]\n", l);

      }

      s=sial_alloc(j+1);
      strncpy(s, p+i-1, j);
      s[j]='\0';
      v=sial_setstrval(sial_newval(), s);
      sial_free(s);
      return v;
}

value_t *
sial_getnstr(value_t* vmadr, value_t* vl)
{
ull madr=sial_getval(vmadr);
ul l=sial_getval(vl);
char *buf=sial_alloc(l+1);
value_t *v;

      if(!API_GETMEM(madr, buf, l)) buf[0]='\0';
      else buf[l]='\0';
      v=sial_setstrval(sial_newval(), buf);
      sial_free(buf);
      return v;
}

value_t *
sial_atoi(value_t *vs, value_t* vbase)
{
char *s=sial_getptr(vs, char);
int base=vbase ? sial_getval(vbase) : 0;

      strtoull(s, 0, (int) base);
      return sial_defbtypesize(sial_newval(), strtoull(s, 0, base), B_ULL);
}

value_t *
sial_itoa(value_t* vi)
{
ull i=sial_getval(vi);
char p[40];
      
      sprintf(p, "%llu", (unsigned long long)i);
      return sial_setstrval(sial_newval(), p);
}

value_t *
sial_strlen(value_t *vs)
{
char *s=sial_getptr(vs, char);
ull l;
      if(!s) l=0;
      else l=strlen(s);

      return sial_defbtype(sial_newval(), l);
}

value_t *
sial_getchar(void)
{
char c; 
struct termio tio, stio;
int in=fileno(stdin);

      if(ioctl(in, TCGETA, &tio)) c=255;
      else {
            stio=tio;
            tio.c_lflag &= ~(ICANON | ECHO);
            tio.c_iflag &= ~(ICRNL  | INLCR);
            tio.c_cc[VMIN] = 1;
            tio.c_cc[VTIME] = 0;
            ioctl(in, TCSETA, &tio);
            c=getc(stdin);
            ioctl(in, TCSETA, &stio);
      }
      return sial_defbtype(sial_newval(), (ull)c);
}

value_t *
sial_gets(void)
{
char p[1024];
      
      if(!fgets(p, sizeof(p)-1, stdin)) p[0]='\0';
      else p[strlen(p)-1]='\0';
      return sial_setstrval(sial_newval(), p);
}

static builtin *bfuncs=0;

/*
      Check for the existance of a bt function
*/
void *
sial_chkbuiltin(char *name)
{
builtin *bf;

      for(bf=bfuncs; bf; bf=bf->next) {

            if(!strcmp(name, bf->v->name)) {

                  return bf;
            }
      }
      return 0;
}

/*
      Remove a builtin.
      This is done when we 'unload' a *.so file.
*/
void
sial_rmbuiltin(var_t*v)
{
builtin *bf;
builtin *last=0;

      for(bf=bfuncs; bf; bf=bf->next) {

            if(!strcmp(v->name, bf->v->name)) {

                  if(!last) bfuncs=bf->next;
                  else {

                        last->next=bf->next;
                  }
                  sial_free(bf->proto);
                  sial_free(bf);
            }
            last=bf;
      }
}

/* 
      Install a new builtin function.
*/
var_t* 
sial_builtin(char *proto, bf_t* fp)
{
var_t*v;

      /* parse the prototype_t*/
      if((v=sial_parsexpr(proto))) {

            builtin *bt;
            int nargs=0;

            /* check name */
            if(!v->name || !v->name[0]) {

                  sial_freevar(v);
                  sial_msg("Syntax error: no function name specified [%s]\n", proto);
                  return 0;
            }

            /* check for function with same name */
            if(sial_chkfname(v->name, 0)) {

                  sial_freevar(v);
                  sial_msg("Function already defined [%s]\n", proto);
                  return 0;
            }

            if(v->dv->fargs) {

                  var_t*vn=v->dv->fargs->next;

                  while(vn!=v->dv->fargs) {

                        nargs++;
                        vn=vn->next;
                  }
            }
            /* check number of args */
            if(nargs > BT_MAXARGS) {

                  sial_freevar(v);
                  sial_msg("Too many parameters to function (max=%d) [%s]\n", BT_MAXARGS, proto);
                  return 0;
            }


            bt=sial_alloc(sizeof(builtin));
            bt->proto=sial_strdup(proto);
            bt->fp=fp;
            bt->v=v;
            bt->next=0;

            /* install it */
            if(!bfuncs) bfuncs=bt;
            else {
                  builtin *btp;

                  for(btp=bfuncs; ; btp=btp->next) if(!btp->next) break;
                  btp->next=bt;
            }
            return v;
      }

      sial_msg("Builtin [%s] not loaded.", proto);

      return 0;
}

#define bcast(f) ((bf_t*)f)

static btspec_t sialbfuncs[] = {
      { "unsigned long long atoi(string, ...)",bcast(sial_atoi)},
      { "int exists(string)",             bcast(sial_exists)},
      { "void exit(int)",                 bcast(sial_bexit)},
      { "int getchar()",                  bcast(sial_getchar)},
      { "string gets()",                  bcast(sial_gets)},
      { "string getstr(char *)",          bcast(sial_getstr)},
      { "string getnstr(char *, int)",    bcast(sial_getnstr)},
      { "string itoa(int)",               bcast(sial_itoa)},
      { "void printf(string, ...)",       bcast(sial_printf)},
      { "void showtemp()",                bcast(sial_showtemp)},
      { "void showaddr(char *)",          bcast(sial_showaddr)},
      { "void memdebugon()",              bcast(sial_memdebugon)},
      { "void memdebugoff()",             bcast(sial_memdebugoff)},
      { "int sial_load(string)",          bcast(sial_bload)},
      { "int sial_unload(string)",        bcast(sial_bunload)},
      { "int depend(string)",             bcast(sial_bdepend)},
      { "int strlen(string)",             bcast(sial_strlen)},
      { "string sprintf(string, ...)",    bcast(sial_sprintf)},
      { "string substr(string, int, ...)",      bcast(sial_substr)},
      { "void prarr(string name, int i)",     bcast(sial_prarr)},
      { "int member(void*, string name)",     bcast(sial_ismember)},
};


/*
      Install the sial builtins.
*/
void
sial_setbuiltins()
{
int i;

      for(i=0;i<sizeof(sialbfuncs)/sizeof(sialbfuncs[0]);i++) {

            (void)sial_builtin(sialbfuncs[i].proto, sialbfuncs[i].fp);
      }
}

value_t* 
sial_exebfunc(char *name, value_t **vals)
{
builtin *bf;
value_t *lvals[BT_MAXARGS*2]; /* use factor 2 for api where char * is 4 bytes */
value_t *v, *vr;


      if((bf=sial_chkbuiltin(name))) {

            int i=0, nargs=0;

            if(vals) for(i=0;vals[i];i++);

            memset(lvals, 0, sizeof(lvals));

            if(bf->v->dv->fargs) {

                  var_t*vv=bf->v->dv->fargs->next;

                  while(vv != bf->v->dv->fargs) {

                        if(vv->name && !strcmp(vv->name, S_VARARG)) { 
                              while(nargs<i) {

                                    lvals[nargs]=sial_cloneval(vals[nargs]);
                                    nargs++;
                              }
                              break; 
                        }

                        /* verify type compatibility and convert */
                        if(vals[nargs]) {

                              lvals[nargs]=sial_cloneval(vv->v);
                              sial_chkandconvert(lvals[nargs], vals[nargs]);
                        }
                        nargs++;
                        vv=vv->next;
                  }
            }

            /* check parameters number */
            if(i<nargs) {

                  sial_rerror(&bf->v->dv->pos, "Too few parameters to '%s'", bf->proto);

            } else if(i>nargs){

                  sial_rerror(&bf->v->dv->pos, "Too many parameters to '%s'", bf->proto);

            }

            if(vals) {
                  /* the actual call */
                  v=(bf->fp) ( 
                        lvals[0],  lvals[1],
                        lvals[2],  lvals[3],
                        lvals[4],  lvals[5],
                        lvals[6],  lvals[7],
                        lvals[8],  lvals[9],
                        lvals[10], lvals[11],
                        lvals[12], lvals[13],
                        lvals[14], lvals[15],
                        lvals[16], lvals[17],
                        lvals[18], lvals[19]
                        );
            } else {

                  v=(bf->fp) ((value_t*)0);
            }

            while(i) {

                  --i;
                  sial_freeval(vals[i]);
                  sial_freeval(lvals[i]);
            }

            /* make a copy of the return value_t info */
            vr=sial_cloneval(bf->v->v);
            sial_chkandconvert(vr, v);
            sial_freeval(v);

            return vr;
      }

      sial_error("Oops. sial_exebfunc()");
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index