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

var.c

/*    Copyright (C) 1998 XIAO, Gang of Universite de Nice - Sophia Antipolis
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

      /* Low-level variable management routines. */

#define VARBUF_LEN      1048576
#define VARNAME_LEN     32768
#define VARNUM_LIMIT    2048
#define vb_internal     1
#define vb_ro           2
#define vb_dirty  4
#define vb_noexport     8

char *_varbuf, *_varptr;      /* main variable value buffer */
char *_varnamebuf, *_varnameptr; /* variable name buffer */

00031 struct vartab {
    char *name, *val;
    long int vlen;
    short int tag;
    unsigned char lvl, nlen;
} *fastvartab, *mainvartab;

int vlenmax[]={1,32,64,128,   256,512,1024,2048,      4096,8192,MAX_LINELEN+1};
int vlenmin[]={0,1,20,45,     100,200,400,800,  1500,3000,6000};
int freelim[]={1,500,500,300, 200,150,100,80,         60,50,50};
#define lvlno (sizeof(vlenmax)/sizeof(vlenmax[0]))
#define freevtot (1+500+500+300 +200+150+100+80 +60+50+50)

int freevars[lvlno], freevstart[lvlno];
int freevcnt=0,bufvcnt=0;
char *freevbuf[freevtot];
int mainvarcnt=0;

      /* initialisation */
void var_init(void)
{
    int i,j;
    memset(freevars,0,sizeof(freevars));
    _varbuf=xmalloc(VARBUF_LEN); _varptr=_varbuf;
    _varnamebuf=xmalloc(VARNAME_LEN); _varnameptr=_varnamebuf;
    mainvartab=xmalloc(VARNUM_LIMIT*sizeof(struct vartab));
    fastvartab=xmalloc(128*sizeof(struct vartab));
    memset(fastvartab,0,128*sizeof(struct vartab));
    for(i=0;i<64;i++) {fastvartab[i].nlen=1; fastvartab[i+64].nlen=2;}
    for(i=j=0;i<lvlno;i++) {freevstart[i]=j; j+=freelim[i];}
}

void exportall(void)
{
    int i, tag; char buf[MAX_LINELEN+MAX_NAMELEN+16];
    
    for(i=0;i<mainvarcnt;i++) {
      tag=mainvartab[i].tag;
      if((tag&vb_dirty)==0 || (tag&vb_noexport)!=0) continue;
      snprintf(buf,sizeof(buf),"%s%s",var_prefix,mainvartab[i].name);
      setenv(buf,mainvartab[i].val,1);
      mainvartab[i].tag&=~vb_dirty;
    }
}

char *vaskbuf(int lvl)
{
    char *p;
    if(lvl>=lvlno) {    /* should never occur */
      module_error("Internal_variable_length_overflow"); return NULL;
    }
    if(freevars[lvl]>0) {
      freevars[lvl]--;
      return freevbuf[freevstart[lvl]+freevars[lvl]];
    }
    if(_varptr+vlenmax[lvl]>=_varbuf+VARBUF_LEN) {
      module_error("variable_buffer_overflow"); return NULL;
    }
    bufvcnt++;
    p=_varptr; _varptr+=vlenmax[lvl]; return p;
}

      /* returns 1 if free succeeded. */
int vfreebuf(int lvl, char *p)
{
    if(p+vlenmax[lvl]>=_varptr) {_varptr=p; bufvcnt--;return 1;}
    if(lvl<=0 || lvl>=lvlno || freevars[lvl]>=freelim[lvl]) return 0;
    freevcnt++;
    freevbuf[freevstart[lvl]+freevars[lvl]]=p; freevars[lvl]++; return 1;
}

int _char_int(char *vn)
{
    int t; char v;
    v=vn[0]; if(vn[1]) t=64; else t=0;
    if(v>='0' && v<='9') return v-'0'+t;
    else {
      if(v>='A' && v<='Z') return v-'A'+10+t;
      else {
          if(v>='a' && v<='z') return v-'a'+10+26+t;
          else return -1;
      }
    }
}

int var_ins(char *name,int inspoint)
{
    int i, nlen, tag;
    if(mainvarcnt>=VARNUM_LIMIT) {
      module_error("too_many_variable_names"); return -1;
    }
    for(nlen=0;nlen<=MAX_NAMELEN && (isalnum(name[nlen]) || name[nlen]=='_');nlen++);
    if(nlen<=1 || nlen>MAX_NAMELEN || name[nlen]!=0) return -1;
    if(_varnameptr+nlen+1>_varnamebuf+VARNAME_LEN) {
      module_error("variable_name_buffer_overflow"); return -1;
    }
    tag=0;
    if(search_list(ro_name,RO_NAME_NO,sizeof(ro_name[0]),name)>=0)
      tag|=vb_ro;
    if(nlen<=2 || strncmp(name,mathfont_prefix,strlen(mathfont_prefix))==0)
      tag|=vb_noexport;
    if(name[0]=='w' && name[1]=='i' && 
       search_list(internal_name,INTERNAL_NAME_NO,sizeof(internal_name[0]),name)>=0)
      tag|=vb_internal;
    i=inspoint; if(i>mainvarcnt) i=mainvarcnt; if(i<0) i=0;
      /* The following 3 lines are anti-bug measures, probably useless. */
    while(i>0 && strcmp(mainvartab[i-1].name,name)>=0) i--;
    while(i<mainvarcnt-1 && strcmp(mainvartab[i+1].name,name)<0) i--;
    if(i<mainvarcnt && strcmp(mainvartab[i].name,name)==0) return i;
    memmove(mainvartab+i+1,mainvartab+i,(mainvarcnt-i)*sizeof(mainvartab[0]));
    mainvarcnt++;
    memmove(_varnameptr,name,nlen); _varnameptr[nlen]=0;
    mainvartab[i].name=_varnameptr; _varnameptr+=nlen+1;
    mainvartab[i].val=NULL; mainvartab[i].vlen=0;
    mainvartab[i].nlen=nlen; mainvartab[i].tag=tag;
    mainvartab[i].lvl=0; return i;
}

char *fast_getvar(char *vname)
{
    int n;

    n=_char_int(vname); if(n<0) return "";
    return fastvartab[n].val;
}

int _setvar_(struct vartab *vtb, char *vval)
{
    int l,lvl;
    char *p;
    if(vval) l=strlen(vval); else l=0;
    if(l>MAX_LINELEN) return 1;
    lvl=vtb->lvl;
    if(l==0) {
      if(lvl<=0) return 0;
      vfreebuf(lvl,vtb->val); vtb->tag|=vb_dirty;
      vtb->lvl=0; vtb->vlen=0;
      if(vval) vtb->val=""; else vtb->val=NULL;
      return 0;
    }
    if(l>=vlenmax[lvl]) {
      vfreebuf(lvl,vtb->val);
      do lvl++; while(l>=vlenmax[lvl]);
      vtb->lvl=lvl;
      vtb->val=p=vaskbuf(lvl);
    }
    else p=vtb->val;
    vtb->vlen=l; vtb->tag|=vb_dirty;
    memmove(p,vval,l); p[l]=0; return 0;
}

int fast_setvar(char *vname, char *vval)
{
    int n;
    
    n=_char_int(vname); if(n<0) return 1;
    return _setvar_(fastvartab+n,vval);
}

      /* internal constant */
int setvar_force=0;

      /* Set a user variable. Now it no longer uses environment.
       * Returns 0 if OK. */
int setvar(char *vname, char *vvalue)
{
    int i,overwrite,tag;

    if(vname[0]!=0 && (vname[1]==0 || (vname[1]=='_' && vname[2]==0)))
      return fast_setvar(vname,vvalue);

    i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname);
    if(i<0) i=var_ins(vname,~i);
    if(i<0) return 1;   /* error */
    overwrite=1; tag=mainvartab[i].tag;
    if(setvar_force==0 && confset==0) {
      if((tag&vb_ro)!=0) overwrite=0;
      else if((tag&vb_internal)!=0 && !trusted_module()) return 1;
    }
    if(!overwrite && mainvartab[i].val!=NULL) return 1;
    _setvar_(mainvartab+i,vvalue);
    if(vname[0]=='w' && strcmp(vname,"wims_print_precision")==0) {
        int a=atoi(vvalue);
      if(a>0 && a<100) print_precision=a;
    }
    return 0;
}

int force_setvar(char *vname,char *vvalue)
{
    int i;
    setvar_force=1; i=setvar(vname,vvalue); setvar_force=0; return i;
}

void unsetvar(char *vname)
{
    int i;
    if(vname[0]!=0 && (vname[1]==0 || (vname[1]=='_' && vname[2]==0))) {
      fast_setvar(vname,NULL); return;
    }
    i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname);
    if(i>=0) _setvar_(mainvartab+i,NULL);
}

#include "mathfonts.c"

      /* Get a variable's value. */
char *_getvar(char *vname)
{
    char *val;
    int i;

    if((untrust&4)!=0) return "";   /* called from !readdef */
    if(vname[0]!=0 && (vname[1]==0 || (vname[1]=='_' && vname[2]==0)))
      return fast_getvar(vname);
    if(!isalnum(vname[0])) return NULL;
    i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname);
    if(i<0) val=NULL; else val=mainvartab[i].val;
    return val;
}

char *getvar(char *vname)
{
    char *val;
    val=_getvar(vname);
    if(val==NULL && memcmp(vname,mathfont_prefix,strlen(mathfont_prefix))==0) 
      val=mathfont(vname);
    return val;
}

      /* output debug information */
void debug_output(void)
{
    long int endmtime, time1;
    struct timeval tv;
    struct rusage us;
    char mbuf[MAX_LINELEN+1];

    if(instex_cnt>0) instex_flush();
    if(gettimeofday(&tv,NULL)) endmtime=0;
    else endmtime=((tv.tv_sec%10000)*1000+tv.tv_usec/1000);
    endmtime=(endmtime-startmtime)%10000000;
    time1=0;
    if(getrusage(RUSAGE_SELF,&us)==0) {
      time1+=us.ru_utime.tv_sec*1000+us.ru_utime.tv_usec/1000;
      time1+=us.ru_stime.tv_sec*1000+us.ru_stime.tv_usec/1000;
    }
    if(getrusage(RUSAGE_CHILDREN,&us)==0) {
      time1+=us.ru_utime.tv_sec*1000+us.ru_utime.tv_usec/1000;
      time1+=us.ru_stime.tv_sec*1000+us.ru_stime.tv_usec/1000;
    }
    snprintf(mbuf,sizeof(mbuf),"<P><CENTER><SMALL>\n\
The server is under debug mode. Your session: %s.<br>\n\
Variable buffer: %d bytes used by %d variables + %d freed chunks.<br>\n\
Processing time %.3f seconds, CPU usage %.2f seconds.<br>\n\
</CENTER></SMALL><P>", getvar("wims_session"),
           _varptr-_varbuf, bufvcnt-freevcnt,freevcnt,
           (double) endmtime/1000, (double) time1/1000);
    output(mbuf);
}


Generated by  Doxygen 1.6.0   Back to index