Subversion Repositories shark

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 *
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "hconf.h"

struct variable vartable[MAXVARIABLES];
struct menu menutable[MAXMENUS];
char *filetable[MAXFILETABLE];
int maxfileindex=0;

long varhelp[MAXVARIABLES];
char helpfilename[FILENAME_MAX];

#if 0
#define printd(fmt,args...) fprintf(stderr,fmt,##args)
#else
#define printd(fmt,args...)
#endif

struct menu *mainmenu=NULL;
char *caption=NULL;

/*
 *
 */


int copystring(char **dstptr, char *src)
{
  int sz;
  if (*dstptr!=NULL) free(*dstptr);
  sz=strlen(src)+1;
  *dstptr=(char*)malloc(sz);
  if (*dstptr==NULL) return -100;
  strcpy(*dstptr,src);
  return 0;
}

/*
 *
 */


int nextvariable=0;

struct variable *findvar(char *s)
{
  int i;
  i=0;
  while (i<nextvariable) {
    if (!strcmp(vartable[i].name,s)) return vartable+i;
    i++;
  }
  return NULL;
}

int findvarindex(struct variable *var)
{
  return (var-vartable);
}

struct variable *newvar(char *s, int type)
{
  struct variable *var;

  /* safety test */
  var=findvar(s);
  if (var!=NULL) {
    if (var->type==NOTYPEVAR) var->type=type;
    else if (var->type!=type) return NULL;
    return var;
  }

  if (nextvariable>=MAXVARIABLES) return NULL;
 
  vartable[nextvariable].name=NULL;
  copystring(&vartable[nextvariable].name,s);
  vartable[nextvariable].type=type;
  vartable[nextvariable].value=NULL;
  vartable[nextvariable].flags=0;
  vartable[nextvariable].fileindex=NOFILEINDEX;

  return vartable+nextvariable++;
}

/* -- */

int nextmenu=0;

struct menu *findmenu(char *s)
{
  int i;
  i=0;
  while (i<nextmenu) {
    if (!strcmp(menutable[i].name,s)) return menutable+i;
    i++;
  }
  return NULL;
}

struct menu *newmenu(char *s)
{
  if (nextmenu>=MAXMENUS) return NULL;
 
  menutable[nextmenu].name=NULL;
  copystring(&menutable[nextmenu].name,s);
  menutable[nextmenu].title=NULL;
  menutable[nextmenu].entries=NULL;
 
  return menutable+nextmenu++;
}

/*
 *
 *
 *
 */


struct _case *newcase(struct menuentry *menuent)
{
  struct _case *c;
  struct _case *n;
  c=malloc(sizeof(struct _case));
  if (c==NULL) return NULL;
  c->next=NULL;
  c->value=NULL;
  c->list=NULL;
  if (menuent->x._case.list==NULL) {
    menuent->x._case.list=c;
    return c;
  }
  n=menuent->x._case.list;
  for (;;) {
    if (n->next==NULL) {
      n->next=c;
      return c;
    }
    n=n->next;
  }
}

struct choice *newchoice(struct menuentry *menuent)
{
  struct choice *c;
  struct choice *n;
  c=malloc(sizeof(struct choice));
  if (c==NULL) return NULL;
  c->next=NULL;
  c->text=NULL;
  c->var=NULL;
  if (menuent->x.choice.list==NULL) {
    menuent->x.choice.list=c;
    return c;
  }
  n=menuent->x.choice.list;
  for (;;) {
    if (n->next==NULL) {
      n->next=c;
      return c;
    }
    n=n->next;
  }
}

struct menuentry *newmenuentry(struct menuentry **ptr)
{
  struct menuentry *n;
  struct menuentry *p;
  n=malloc(sizeof(struct menuentry));
  if (n==NULL) return NULL;
  n->next=NULL;
  n->type=0;
  if (*ptr==NULL) {
    *ptr=n;
    return n;
  }
  p=*ptr;
  for (;;) {
    if (p->next==NULL) {
      p->next=n;
      return n;
    }
    p=p->next;
  }
}

int newfile(char *s)
{
  if (maxfileindex==MAXFILETABLE) return NOFILEINDEX;
  filetable[maxfileindex]=malloc(strlen(s)+1);
  if (filetable[maxfileindex]==NULL) return NOFILEINDEX;
  strcpy(filetable[maxfileindex],s);
  maxfileindex++;
  return maxfileindex-1;
}

/*
 *
 *
 *
 */


/*
 *
 *
 *
 */


int parsebool(struct menuentry **ptr);
int parsetristate(struct menuentry **ptr);
int parserange(struct menuentry **ptr);
int parsesubmenu(struct menuentry **ptr);
int parsecase(struct menuentry **ptr);
int parsechoice(struct menuentry **ptr);
int parseseparator(struct menuentry **ptr);

int parsemenufield(struct menuentry **ptr)
{
  char *s;

  s=gettoken();
  if (s==NULL) return -999;

  if (!strcmp(s,"bool")) return parsebool(ptr);
  if (!strcmp(s,"tristate")) return parsetristate(ptr);
  if (!strcmp(s,"range")) return parserange(ptr);
  if (!strcmp(s,"submenu")) return parsesubmenu(ptr);
  if (!strcmp(s,"switch")) return parsecase(ptr);
  if (!strcmp(s,"choice")) return parsechoice(ptr);
  if (!strcmp(s,"separator")) return parseseparator(ptr);

  return -333;
}

/* --- */

int parsecase(struct menuentry **ptr)
{
  char *s;
  struct menuentry *ent;
  struct _case *cas=NULL;
  struct variable *v;
  int res;

  printd("start parseswitch()\n");

  ent=newmenuentry(ptr);
  if (ent==NULL) return -31;
  ent->type=CASEENTRY;
  ent->x._case.list=NULL;
   
  s=gettoken();
  if (s==NULL) return -32;
  v=findvar(s);
  if (v==NULL) return -36;
  ent->x._case.var=v;
  v->flags|=FLAG_M;

  for (;;) {
    s=gettoken();
    if (!strcmp(s,"endswitch")) break;
   
    if (!strcmp(s,"case")) {
      cas=newcase(ent);
      if (cas==NULL) return -34;
      s=gettoken();
      if (s==NULL) return -35;
      if (*s!='\"') return -35;
      cas->value=NULL;
      copystring(&cas->value,s+1);
      continue;
    }

    if (cas==NULL) return -39;

    ungettoken();
    res=parsemenufield(&cas->list);
    if (res) return res;
  }

  return 0;
}

int parsechoice(struct menuentry **ptr)
{
  struct menuentry *ent;
  struct choice *cho;
  struct variable *v;
  char *def;
  int defdone;
  char *s;

  printd("start parsechoice()\n");

  ent=newmenuentry(ptr);
  if (ent==NULL) return -31;
  ent->type=CHOICEENTRY;
  ent->x.choice.list=NULL;
  ent->x.choice.act=NULL;
  ent->x.choice.numchoices=0;

  s=gettoken();
  if (s==NULL) return -32;
  if (*s!='\"') return -33;
  ent->x.choice.text=NULL;
  copystring(&ent->x.choice.text,s+1);

  defdone=0;
  def=NULL;
  s=gettoken();
  if (s==NULL) return -39;
  if (*s!='\"') {
    copystring(&def,s);
  } else
    ungettoken();

  for (;;) {
    s=gettoken();
    if (s==NULL) return -34;
    if (!strcmp(s,"endchoice")) {
      if (def==NULL||!defdone) return -37;
      free(def);
      break;
    }

    if (*s!='\"') return -38;

    cho=newchoice(ent);
    ent->x.choice.numchoices++;
    if (cho==NULL) return -33;
    cho->text=NULL;
    copystring(&cho->text,s+1);
   
    s=gettoken();
    if (s==NULL) return -34;    
    v=newvar(s,CHOICEVAR);
    if (v==NULL) return -37;
    cho->var=v;
    v->value=NULL;
    copystring(&v->value,"n");

    if (def==NULL) {
      ent->x.choice.act=cho;
      copystring(&def,s);
      defdone=1;
    } else if (!strcmp(def,s)) {
      ent->x.choice.act=cho;
      defdone=1;
    }
  }

  return 0;
}

int parsebool(struct menuentry **ptr)
{
  struct menuentry *ent;
  struct variable *var;
  char *s;

  printd("start parsebool()\n");

  ent=newmenuentry(ptr);
  if (ent==NULL) return -50;
  ent->type=BOOLENTRY;

  s=gettoken();
  if (s==NULL) return -51;
  if (*s!='\"') return -55;
  ent->x.bool.text=NULL;
  copystring(&ent->x.bool.text,s+1);
 
  s=gettoken();
  if (s==NULL) return -52;
  var=newvar(s,BOOLVAR);
  if (var==NULL) return -53;
  ent->x.bool.var=var;

  s=gettoken();
  if (*s!='\"') {
    ungettoken();
    var->value=(char *)malloc(2);
    var->value[0]='n';
    var->value[1]='\0';
    return 0;
  }
  if (*(s+1)=='\0') return -54;
  var->value=NULL;
  copystring(&var->value,s+1);

  return 0;
}

int parseseparator(struct menuentry **ptr)
{
  struct menuentry *ent;

  printd("start parseseparator()\n");

  ent=newmenuentry(ptr);
  if (ent==NULL) return -50;
  ent->type=SEPARATORENTRY;

  return 0;
}

int parserange(struct menuentry **ptr)
{
  struct menuentry *ent;
  struct variable *var;
  char *s;
  int v;

  printd("start parserange()\n");

  ent=newmenuentry(ptr);
  if (ent==NULL) return -60;
  ent->type=RANGEENTRY;

  s=gettoken();
  if (s==NULL) return -61;
  if (*s!='\"') return -65;
  ent->x.range.text=NULL;
  copystring(&ent->x.range.text,s+1);

  s=gettoken();
  if (s==NULL) return -62;
  var=newvar(s,RANGEVAR);
  if (var==NULL) return -63;
  ent->x.range.var=var;

  s=gettoken();
  if (s==NULL) return -66;
  ent->x.range.minval=atoi(s);
  if (ent->x.range.minval==0&&strcmp(s,"0")) return -67;

  s=gettoken();
  if (s==NULL) return -66;
  ent->x.range.maxval=atoi(s);
  if (ent->x.range.maxval==0&&strcmp(s,"0")) return -68;

  s=gettoken();
  if (s==NULL) return -69;
  v=atoi(s);
  if (v==0&&strcmp(s,"0")) {
    ungettoken();
    v=ent->x.range.minval;
  }

  {
    char buffer[256];
    sprintf(buffer,"%i",v);
    var->value=NULL;
    copystring(&var->value,buffer);
  }
 
  return 0;
}

int parsetristate(struct menuentry **ptr)
{
  struct menuentry *ent;
  struct variable *var;
  char *s;

  printd("start parsetristate()\n");

  ent=newmenuentry(ptr);
  if (ent==NULL) return -50;
  ent->type=TRISTATEENTRY;

  s=gettoken();
  if (s==NULL) return -51;
  if (*s!='\"') return -55;
  ent->x.tristate.text=NULL;
  copystring(&ent->x.tristate.text,s+1);

  s=gettoken();
  if (s==NULL) return -52;
  var=newvar(s,TRISTATEVAR);
  if (var==NULL) return -53;
  ent->x.tristate.var=var;

  s=gettoken();
  if (*s!='\"') {
    ungettoken();
    var->value=(char *)malloc(2);
    var->value[0]='n';
    var->value[1]='\0';
    return 0;
  }
  if (*(s+1)=='\0') return -54;
  var->value=NULL;
  copystring(&var->value,s+1);

  return 0;
}

int parsesubmenu(struct menuentry **ptr)
{
  struct menuentry *ent;
  char *s;

  printd("start parsesubmenu()\n");

  ent=newmenuentry(ptr);
  if (ent==NULL) return -40;
  ent->type=SUBMENUENTRY;
 
  s=gettoken();
  if (s==NULL) return -41;
  if (*s!='\"') return -43;
  ent->x.submenu.text=NULL;
  copystring(&ent->x.submenu.text,s+1);

  s=gettoken();
  if (s==NULL) return -42;
  ent->x.submenu.menuname=NULL;
  ent->x.submenu.menu=NULL;
  copystring(&ent->x.submenu.menuname,s);

  return 0;
}

int parsetitle(struct menu *ptr)
{
  char *s;

  printd("start parsetitle()\n");

  s=gettoken();
  if (s==NULL) return -71;
  ptr->title=NULL;
  copystring(&ptr->title,s+1);
  return 0;
}

int parsecaption(void)
{
  char *s;

  printd("start parsecaption()\n");

  s=gettoken();
  if (s==NULL) return -91;
  caption=NULL;
  copystring(&caption,s+1);
  return 0;
}

int parsemenu(void)
{
  struct menu *ptr;
  char *s;
  int ret;

  printd("start parsemenu()\n");
  ret=0;

  s=gettoken();
  if (s==NULL) return -12;
  ptr=newmenu(s);
  if (ptr==NULL) return -15;

  for (;;) {
    s=gettoken();
    if (!strcmp(s,"endmenu")) return 0;

    if (!strcmp(s,"title")) {
      ret=parsetitle(ptr);
      if (ret) return ret;
      continue;
    }

    ungettoken();
    ret=parsemenufield(&ptr->entries);    
    if (ret) break;
  }

  return ret;
}

int parsefile(void)
{
  struct variable *var;
  char *s;
  int index;
  int ret;

  printd("start parsefile()\n");
  ret=0;

  s=gettoken();
  if (s==NULL) return -112;  
  index=newfile(s);
  if (index==-1) return -115;

  for (;;) {
    s=gettoken();
    if (!strcmp(s,"endfile")) return 0;

    var=newvar(s,NOTYPEVAR);
    if (var==NULL) return -117;
    var->fileindex=index;
  }

  return ret;
}

/*
 *
 */


int resolvmenuentries(struct menuentry *ptr)
{
  struct _case *ca;
  int res,i;

  while (ptr!=NULL) {
    switch(ptr->type) {
    case BOOLENTRY:
      break;
    case TRISTATEENTRY:
      break;
    case SUBMENUENTRY:
      ptr->x.submenu.menu=findmenu(ptr->x.submenu.menuname);
      if (ptr->x.submenu.menu==NULL) return -10;
      break;
    case CHOICEENTRY:
      break;
    case CASEENTRY:
      ca=ptr->x._case.list;
      i=1;
      while (ca!=NULL) {
        res=resolvmenuentries(ca->list);
        if (res) return res;
        ca=ca->next;
        i++;
      }
      break;
    }
    ptr=ptr->next;
  }

  return 0;
}

static int resolv(void)
{
  int res,i;

  i=0;
  while (i<nextmenu) {
    res=resolvmenuentries(menutable[i].entries);
    if (res) return res;
    i++;
  }

  return 0;
}

/*
 *
 */


int parse(void)
{
  char *s;
  int ret;
  ret=0;
  while ((s=gettoken())!=NULL) {
    if (!strcmp(s,"menu")) ret=parsemenu();
    else if (!strcmp(s,"caption")) ret=parsecaption();
    else if (!strcmp(s,"file")) ret=parsefile();
    else ret=-1;
    if (ret) break;
  }
  return ret;
}

int parsehelp(char *filename)
{
  struct variable *var;
  char buffer[256];
  FILE *fin;
  char *s;
  int i;
 
  fin=fopen(filename,"rt");
  if (fin==NULL) return 0;

  while (fgets(buffer,sizeof(buffer),fin)!=NULL)
    if (*buffer=='@') {
      s=strchr(buffer,'\n');
      if (s!=NULL) *s='\0';
      var=findvar(buffer+1);
      if (var==NULL) {
        fprintf(stderr,"help var %s not found config file",buffer);
        return -845;
      }
      i=findvarindex(var);
      varhelp[i]=ftell(fin);
    }
 
  fclose(fin);
  return 0;
}

int readconfigin(char *filename)
{
  char *ptr;
  int res;

  res=init_tokenizer(filename,0x01);
  if (res) return res;

  res=parse();
  if (res) return res;

  res=done_tokenizer();
  if (res) return res;

  res=resolv();
  if (res) return res;

  mainmenu=findmenu("main");
  if (mainmenu==NULL) return -97;

  /* -- */
 
  ptr=strstr(filename,".in");  
  if (ptr!=NULL) *ptr='\0';
  else {
    ptr=strchr(filename,'.');
    if (ptr!=NULL) *ptr='\0';
  }

  strcpy(helpfilename,filename);
  strcat(helpfilename,".hlp");

  res=parsehelp(helpfilename);
  if (res) return res;

  return 0;
}

/*
 *
 *
 *
 */


void dumpvariables(void)
{
  int i;

  fprintf(stderr,"VARIABLES TABLE\n---------------\n\n");
  i=0;
  while (i<nextvariable) {
    fprintf(stderr,"name:  -%s-\n",vartable[i].name);
    if (vartable[i].value!=NULL)
      fprintf(stderr,"value: \"%s\"\n",vartable[i].value);
    else
      fprintf(stderr,"value: NO VALUE\n");
    fprintf(stderr,"flags: 0x%04x\n",vartable[i].flags);
    fputc('\n',stderr);
    i++;
  }
}

#if 0

void dumpmenuentrytype(struct menuentry *ptr,char *s)
{
  fprintf(stderr,"%s entry type  : ",s);
  switch(ptr->type) {
  case BOOLENTRY: fprintf(stderr,"bool\n"); break;
  case SUBMENUENTRY: fprintf(stderr,"submenu\n"); break;
  case TRISTATEENTRY: fprintf(stderr,"tristate\n"); break;
  case CHOICEENTRY: fprintf(stderr,"choice\n"); break;
  case CASEENTRY: fprintf(stderr,"case\n"); break;
  default: fprintf(stderr,"unknown\n"); break;
  }
}

void dumpmenuentries(struct menuentry *ptr,int x)
{
  struct choice *cho;
  struct _case *ca;
  char blanks[64];
  int i;
  memset(blanks,' ',sizeof(blanks));
  blanks[x-1]='\0';
  while (ptr!=NULL) {
    dumpmenuentrytype(ptr,blanks);
    switch(ptr->type) {
    case BOOLENTRY:
      fprintf(stderr,"%s text        : '%s'\n",blanks,ptr->x.bool.text);
      fprintf(stderr,"%s variable    : %s\n",blanks,ptr->x.bool.var->name);
      break;
    case TRISTATEENTRY:
      fprintf(stderr,"%s text        : '%s'\n",blanks,ptr->x.tristate.text);
      fprintf(stderr,"%s variable    : %s\n",blanks,ptr->x.tristate.var->name);
      break;
    case SUBMENUENTRY:
      fprintf(stderr,"%s text        : '%s'\n",blanks,ptr->x.submenu.text);
      fprintf(stderr,"%s submenu     : %s\n",blanks,ptr->x.submenu.menu->name);
      break;
    case CHOICEENTRY:
      fprintf(stderr,"%s text        : '%s'\n",blanks,ptr->x.choice.text);
      fprintf(stderr,"%s def variable: %s\n",blanks,ptr->x.choice.act->var->name);
      i=1;
      cho=ptr->x.choice.list;
      while (cho!=NULL) {
        fprintf(stderr,"%s text %i      : '%s'\n",blanks,i,cho->text);
        fprintf(stderr,"%s variable %i  : %s\n",blanks,i,cho->var->name);
        i++;
        cho=cho->next;
      }
      break;
    case CASEENTRY:
      fprintf(stderr,"%s variable    : %s\n",blanks,ptr->x._case.var->name);
      fputc('\n',stderr);
      ca=ptr->x._case.list;
      i=1;
      while (ca!=NULL) {
        fprintf(stderr,"%s value %i     : '%s'\n",blanks,i,ca->value);
        dumpmenuentries(ca->list,x+2);
        ca=ca->next;
        i++;
      }
      break;
    }
    fputc('\n',stderr);
    ptr=ptr->next;
  }
}

void dumpmenus(void)
{
  int i;

  fprintf(stderr,"MENUS TABLE\n-----------\n\n");
  i=0;
  while (i<nextmenu) {
    fprintf(stderr,"name:  %s\n",menutable[i].name);
    fprintf(stderr,"text:  '%s'\n",menutable[i].comment);
    fputc('\n',stderr);
    dumpmenuentries(menutable[i].entries,2);
    //fputc('\n',stderr);
    i++;
  }
}
#endif