
/* $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 "lx_support.h"

#include "acf_yacc.h"
#include "cmdexec.h"
#include "cmdlog.h"
#include "cmdparse.h"
#include "cmdutil.h"
#include "database.h"
#include "expression.h"
#include "generic.h"
#include "vertcl_main.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.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');
}