/* * Copyright 2001 Silicon Graphics, Inc. All rights reserved. */ #include #include #include #include #include #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= 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)}, { "string findsym(string)", bcast(sial_findsym)}, }; /* Install the sial builtins. */ void sial_setbuiltins() { int i; for(i=0;iv->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(nargsv); sial_chkandconvert(lvals[nargs], vals[nargs]); } nargs++; vv=vv->next; } } /* check parameters number */ if(iv->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; }