#include <stdio.h>
#include <string.h>
char *getenv();
#include <unistd.h>
#define MAX_BUF 1025

/* ====================  search sequence: =============
 //machine
 path/tail -  tail in path/.objects [local]
 /jgpath/tail - tail in OBJECT_ROOT/jgpath/.objects
 /jgpath/tail - tail in OBJECT_ROOT/jgpath/.remoteobjects
 path/exec - executeable program METHOD_ROOT/path/exec
         [local || dctcount<8 (not first pass)]
 path/datafile - use def method on local file [local]
   ===================================================== */

int scandct(s,t)
char *s,*t;
{
  FILE *fdic;
  char tdic[MAX_BUF],dctname[MAX_BUF],*sp;
  int nok;
#ifdef DEBUG
  printf("Searching >%s< for >%s<\n",s,t);
#endif
  sp=strrchr(t,'/');
  if(sp){
    *(sp++)=0;
    strcpy(dctname,t);
    strcat(dctname,"/");
    strcat(dctname,s);
  } else {
    strcpy(dctname,s);
    sp=t;
  };
  strcat(sp,"=");
#ifdef DEBUG
  printf("Open >%s< and look for >%s<\n",dctname,sp);
#endif
  fdic=fopen(dctname,"r");
  if(fdic==NULL)return 0;

  nok=1;
  while (!feof(fdic) && nok)
    {
    fgets(tdic,MAX_BUF-1,fdic);
    if (strstr(tdic,sp)==tdic) nok=0;
    };
  fclose(fdic);
  if (nok) return 0;

  strcpy(t,strchr(tdic,'=')+1);
  if(t[strlen(t)-1]=='\n')t[strlen(t)-1]=0;
  if(sp=strchr(t,' ')){
    *sp=0;
    sp=strtok(sp+1," ");
    while(sp){putenv(sp);sp=strtok(NULL," ");};
  };
  return 1;
}

void mergeparams(req,dct)
char *req,*dct;
{
  char tmp[MAX_BUF],*j,*k;
  int i,dctopt,reqproj,nb;

  /* no params in dictionary */
  if(dct==NULL)return;

  /* no params requested */
  if(*req==0){
    j=dct+1;
    k=req;
    while(*j){
      if(*j == '[' || *j == ']') j++;
      else *(k++)= *(j++);
    };
    *dct=0;
    *(k-1)=0;
    return;
  };

  /* dictionary params first */

  nb=0;
  dctopt=1;
  j=dct;
  k=tmp;
  while(*(++j)){
    switch(*j){
      case '[':nb++;dctopt=0;break;
      case ']':nb--;break;
      default:if(nb==0) *(k++) = *j;break;
      };
  };
  if(k>tmp) if(*(k-1) == ')') *(k-1)=',';

  j=req-1;
  reqproj=0;
  nb=0;
  i=1;
  while(*(++j)){
    *(k++)= *j;
    switch(*j){
      case '(':nb++;break;
      case ')':nb--;break;
      case '<':
      case '>':
      case '=':i=0;break;
      case ',':if(nb==0 && i==1)reqproj=1;
	i=1;
	break;
      };
  };
  *k=0;

  if(reqproj || dctopt) {
    while(j=strstr(tmp,",,"))strcpy(j,j+1);
    strcpy(req,tmp);
    *dct=0;
    return;
  };

  j=dct;
  nb=0;
  while(*(++j)){
    switch(*j){
      case '[':nb++;break;
      case ']':nb--;break;
      default:if(nb) *(k++) = *j;break;
      };
  };
  if(k>tmp) { 
    if(*(k-1) == ',') *(k-1)=0; else *k=0;
    while(j=strstr(tmp,",,"))strcpy(j,j+1);
    strcpy(req,tmp);
  } else *req=0;
  *dct=0;
  return;
}


int dctsearch(obj,method,params,localflag)
char *obj,*method,*params;
int localflag;
{
  char pathreq[MAX_BUF],metreq[MAX_BUF],parreq[MAX_BUF];
  char *j;
  char tmp[MAX_BUF];
  int dctcount;
  int dctnfound;

  strcpy(pathreq,obj);
  strcpy(parreq,params);

  *method=0;
  *params=0;

  dctcount=8;

  while(dctcount){

    dctnfound=1;

    /* //machine ... */
#ifdef DEBUG
    printf("test // ... %s**%s\n",pathreq,parreq);
#endif
    if(strstr(pathreq,"//")==pathreq){
      strcpy(method,pathreq);
      strcpy(params,parreq);
      return 1;
    };

    /* check for object dictionary */
    if(localflag){
      strcpy(tmp,pathreq);
#ifdef DEBUG
    printf("test local obj... %s**%s\n",tmp,parreq);
#endif
      if(scandct(".objects",tmp)){
	j=strchr(tmp,'(');
	if(j)mergeparams(parreq,j);
	if(strstr(tmp,"//")==tmp){
	  strcpy(method,tmp);
	  strcpy(params,parreq);
	  return 1;
	};
	strcpy(pathreq,tmp);
	dctnfound=0;
      };
    };
    
    /* check system .objects dictionary */
    if(dctnfound && *pathreq == '/'){
      strcpy(tmp,OBJECT_ROOT);
      if(*pathreq){
	strcat(tmp,"/");
	strcat(tmp,pathreq);
      };
#ifdef DEBUG
    printf("test sys local ... %s**%s\n",tmp,parreq);
#endif
      if(scandct(".objects",tmp)){
	j=strchr(tmp,'(');
	if(j)mergeparams(parreq,j);
	if(strstr(tmp,"//")==tmp){
	  strcpy(method,tmp);
	  strcpy(params,parreq);
	  return 1;
	};
	strcpy(pathreq,tmp);
	dctnfound=0;
      };
    };
    
    /* check system  .remoteobjects dictionary */
    if(dctnfound && *pathreq == '/'){
      strcpy(tmp,OBJECT_ROOT);
      if(*pathreq){
	strcat(tmp,"/");
	strcat(tmp,pathreq);
      };
#ifdef DEBUG
    printf("test sys global ... %s**%s\n",tmp,parreq);
#endif
      if(scandct(".remoteobjects",tmp)){
	j=strchr(tmp,'(');
	if(j)mergeparams(parreq,j);
	if(strstr(method,"//")==method){
	  strcpy(method,tmp);
	  strcpy(params,parreq);
	  return 1;
	};
	strcpy(pathreq,tmp);
	dctnfound=0;
      };
    };
    
    /* check for system method */
    if(dctnfound && (localflag || dctcount<8)){
      strcpy(tmp,METHOD_ROOT);
      strcat(tmp,pathreq);
#ifdef DEBUG
    printf("test sys meth ... %s**%s\n",tmp,parreq);
#endif
      if(access(tmp,X_OK)==0){
	strcpy(method,tmp);
	strcpy(params,parreq);
	return 1;
      };
    };

    /* local file - use default method */
    if(dctnfound && localflag){
#ifdef DEBUG
    printf("test def file ... %s**\n",pathreq);
#endif
      if(access(pathreq,R_OK)==0){
	strcpy(tmp,"(");
	strcat(tmp,pathreq);
	strcat(tmp,")");
	mergeparams(parreq,tmp);
	strcpy(pathreq,"def");
	dctnfound=0;
      };
    };

    /* error */
    if(dctnfound){
      strcpy(method,"Cannot be found in dictionary:");
      return 0;
    };
    dctcount--;
  };
strcpy(method,"Too many iterations in dictionary - check for loops:");
return 0;
}

/*
main(argc,argv)
int argc;
char *argv[];
{
char met[1024],par[1024];
int i;
if(dctsearch(argv[1],met,par,1))
  printf("dctsearch = %s**%s\n",met,par);
else printf("Not found\n");
}
*/
