
/* $Id: lx_support.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $
 *
 * $Log: lx_support.c,v $
 * Revision 1.1.1.1  2003/11/04 23:34:57  mjames
 * Imported into local repositrory
 *
 * Revision 1.8  2002/09/09 10:29:56  mjames
 * Moved pin remapping function to pin ident editing function from
 * sorting pin name routine.
 *
 * Revision 1.7  2002/01/16 11:22:45  mjames
 * database.h header file is read in first as it undefined DLL stuff irrelevant
 * to HPUX
 *
 * Revision 1.6  2002/01/15 12:34:12  mjames
 * DLL declarations put in
 *
 * Revision 1.5  2001/12/13 22:14:25  mjames
 * Corrected nested command handlers to allow variable passing without corruption.
 *
 * Revision 1.4  2001/10/31 22:20:08  mjames
 * Tidying up problematical comments caused by CVS
 * 'intelligent' comment guessing
 *
 * 
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "expression.h"
#include "generic.h"
#include "database.h"


#include "vertcl_main.h"
#include "lx_support.h"



#include "cmdparse.h"
#include "cmdlog.h"
#include "cmdutil.h"
#include "cmdexec.h"

#include "acf_yacc.h"


/* purpose to queue lex tokens until all have been used on a line or in a statement */

int yyval; /* propose to confuse LEX ... */
int     yy_nArgs;
char ** yy_Args;

#ident "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/lx_support.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $"

__declspec (dllexport)struct str  * lx_first = NULL;
__declspec (dllexport)struct str  * lx_last  = NULL;




/* the Args values are for the current argc/argv context */
void expand_string( char * source , char * dest, int nArgs, char * Args[]) {
   char num_buff[LINELEN];

   char * Ptr = source;
   char * Optr= dest;
   generic_info_t ** chip_generics = NULL;
   
/*   printf("IN ='%s'\n",source);  */ 
   
   if(!source || !dest)
     return;


   dest[0] = 0;
   while(*Ptr && (Optr-dest)<LINELEN-1) {
            
     if(*Ptr=='\\') {
       Ptr++; 
       if (*Ptr) {
         *Optr++ = *Ptr++;
         *Optr = 0;
         }; 
       continue;
       };

     if(*Ptr=='$') { /* variable expansion */
            
       /* pattern 1 : $n - lookup argv[n] */
       if(Ptr[1] >='0' && Ptr[1] <='9') {
         int n = Ptr[1]-'0';
         if (n < nArgs ) { 
    
           /* space to place new word ? */
           if((Optr+strlen(Args[n])-dest)<LINELEN ) { 
             strcpy(Optr, Args[n]);
             Optr+= strlen(Args[n]);
             *Optr = 0; 
             };
    
           Ptr+=2;
           continue; 
           }
         }
        /* pattern 2 : look up a generic SYSVAR */
       else if (Ptr[1]=='(') { 
         char var_name[WORDWIDTH], * env_val;
          int c = 0;
          generic_info_t generic[1];
          generic_type_t gen_type;
          Ptr+=2; /* skip '$(' */
          var_name[0] = '\0';
          while(*Ptr && *Ptr != ')') {
            if(c<WORDWIDTH-1) {
              var_name[c++] = *Ptr;
              var_name[c]   = '\0';
              }
            Ptr++;
            }
          if(*Ptr) Ptr++;
          /* now lookup result */
          
          env_val = NULL;
          /* try generic lookup first */

          gen_type = get_generic_value(&global_generics,var_name,generic);
          if(!gen_type)
            gen_type = get_generic_value(&partition_generics,var_name,generic);
          /* accept a string */
          if (gen_type==IS_STRING || gen_type == IS_ENV_VAL) { 
             if(generic->expr)
               env_val = generic->expr->left.s;
             };
          if (gen_type==IS_INTEGER)
             {
             if(generic->expr)
               {
               sprintf(num_buff,"%d",eval_expression(generic->expr,chip_generics));
               env_val = num_buff;
               }
             }  
          if (gen_type==TO)
             {
             if(generic->expr)
               {
               sprintf(num_buff,"%d TO %d",eval_expression(generic->expr->left.e,chip_generics),eval_expression(generic->expr->right.e,chip_generics));
               env_val = num_buff;
               }
             }  
          if (gen_type==DOWNTO)
             {
             if(generic->expr)
               {
               sprintf(num_buff,"%d DOWNTO %d",eval_expression(generic->expr->left.e,chip_generics),eval_expression(generic->expr->right.e,chip_generics));
               env_val = num_buff;
               }
             }  


           /* try OS environment variables */
          if (!env_val) 
             env_val = getenv(var_name);
          if (env_val && (Optr+strlen(env_val)-dest)<LINELEN ) { 
             strcpy(Optr,env_val );
             Optr+= strlen(env_val);
             *Optr = 0; 
             continue;
            };
          if ((Optr+strlen(var_name)-dest)<LINELEN ) { 
            sprintf(Optr,"$(%s)",var_name);
            Optr+= strlen(var_name)+3;
            *Optr = 0; 
            }
                          
         }
       }
     if(*Ptr != '\r' && *Ptr != '\n')
       {
       *Optr++ = *Ptr;
       *Optr = 0; 
       }
     Ptr++;
     }
 /*  printf("OUT='%s'\n",dest);  */
 }

char * make_string(char * token ,struct str ** pfirst,struct str ** plast )
  {
  char       * t;
  struct str * s;
  int l;
  char workbuff[LINELEN];
  /* perform checks in the right order 18-02-2000 */
  if(!token)
    return NULL;
  l = strlen(token);
  s = calloc(1,sizeof(struct str ));
  if (!s)
    return NULL;
  
  /* eliminate quotes from the string :
   * !! ASSUMES string is in Read/Write memory  */
  if (l>=2 && token[0]=='\"' && token[l-1]=='\"')
    {
    strncpy (token,token+1,l-2); /* chuck quotes off string */
    token[l-2] = '\0';           /* null terminate */
    }
   
  
  /* the values yy_nArgs and yy_Args were filled 
     in just before calling yyparse */
  expand_string(token,workbuff,yy_nArgs,yy_Args);
  l = strlen(workbuff);
    
  t = malloc(l+1);
  if (!t) 
    return NULL;

  strcpy(t,workbuff);       /* copy string , join to structure */
  s->dat = t;
  s->next = NULL;




  if (!*pfirst)
    *pfirst = s;

  if(*plast)
    (*plast)->next = s;

  *plast = s;
/*  printf("MADE\n"); */


  return (t);  /* pointer to the string that can be later tidily freed */



  }


void free_strings( struct str ** pfirst, struct str ** plast)
  {
  struct str * s,* t;
  s = *pfirst;
  while(s)       /* run down the list, freeing entries */
    {
    if (s->dat)
      free(s->dat);
    t = s;
    s= s->next;
    free(t);
    }
  *pfirst = NULL;
  *plast = NULL;

  }


/* called from YACC to deallocate memory structures cleanly */
void free_lex_strings(void) {
  free_strings(&lx_first,&lx_last);
  };

#define to_lower(c) ((c>='A' && c<='Z') ? c-'A'+'a':c)


int streq(char    *s1,char    *s2)
{
    while (*s1 != '\0') {
        if (to_lower(*s2) != to_lower(*s1))
            return( 0 );
        s1++;
        s2++;
    }
    return( *s2 == '\0' );
}


int strneq(char    *s1,char    *s2,int n)
{
    while (n && *s1 != '\0' ) {
        if (to_lower(*s2) != to_lower(*s1))
            return( 0 );
        s1++;
        s2++;
        --n;
    }
    return( n==0 || *s2 == '\0' );
}
