/*
Zz Dynamic Parser Library
Copyright (C) 1989 - I.N.F.N - S.Cabasino, P.S.Paolucci, G.M.Todesco
The Zz Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The Zz Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "zlex.h"
#include "rule.h"
#include "err.h"
#include "mem.h"
#include "param.h"
#include "trace.h"
#define PARAM_SCOPE_STACK_SIZE 50
struct s_param_pair {
char *name;
char global;
struct s_content cnt;
struct s_param_pair *next;
};
static struct s_param_pair *param_first_free=0;
static struct s_param_pair *param_scope_stack[PARAM_SCOPE_STACK_SIZE];
static int param_level=1; /* per provare a risolvere il /inutile=maserve */
static int param_mem=0;
/*------------------------------------------------------------------------*/
static struct s_param_pair *new_param_pair()
{
struct s_param_pair *pair;
if(param_first_free)
{
pair=param_first_free;
param_first_free=pair->next;
}
else
{
pair = (struct s_param_pair*)malloc(sizeof(struct s_param_pair));
param_mem += sizeof(struct s_param_pair);
}
pair->global=0;
pair->next=0;
pair->name=0;
pair->cnt.tag=tag_none;
return pair;
}
/*------------------------------------------------------------------------*/
static void free_param_pair(struct s_param_pair *pair)
{
pair->next=param_first_free;
pair->name=0;
pair->cnt.tag=tag_none;
param_first_free = pair;
}
/*------------------------------------------------------------------------*/
int push_param_scope(void)
{
if(param_level>=PARAM_SCOPE_STACK_SIZE-1)
zz_error(ERROR,"too many Zz variable scopes");
else
{
param_scope_stack[param_level++] = 0;
}
return 0;
}
/*------------------------------------------------------------------------*/
int pop_param_scope(void)
{
struct s_param_pair *pair,*tmp;
if(param_level>0)
{
param_level--;
pair = param_scope_stack[param_level];
while(pair)
{
tmp=pair;
pair=pair->next;
if(tmp->cnt.tag->param_off)
(*tmp->cnt.tag->param_off)(&(tmp->cnt),tmp->name);
free_param_pair(tmp);
}
}
return 0;
}
/*------------------------------------------------------------------------*/
/*
returns 1 if a new zz variable was crated, 0 otherwise
*/
int set_param(name,cnt)
char *name;
struct s_content *cnt;
{
struct s_param_pair *pair;
struct s_content *old;
int i,ret;
zz_assert(name);
zz_trace("set_param(%s,%z)\n", name, cnt);
if(strcmp(name,"$")==0)
return 1;
if(param_level<=0)
push_param_scope();
i = param_level-1;
pair = param_scope_stack[i];
while(pair && pair->name!=name)pair=pair->next;
if(pair)
{
if(pair->cnt.tag->param_off)
(*pair->cnt.tag->param_off)(&(pair->cnt),pair->name);
ret=0;
}
else
{
pair = new_param_pair();
pair->name = name;
pair->next = param_scope_stack[i];
param_scope_stack[i]=pair;
ret=1;
}
if(cnt->tag->param_on)
(*cnt->tag->param_on)(cnt,name);
pair->cnt = *cnt;
pair->global=0;
return ret;
}
/*------------------------------------------------------------------------*/
int gset_param(char *name, struct s_content *cnt)
{
struct s_param_pair *pair;
struct s_content *old;
int i;
if(strcmp(name,"$")==0) return 1;
if(param_level<=0) push_param_scope();
i=0;
pair = param_scope_stack[i];
while(pair && pair->name!=name)pair=pair->next;
if(pair)
{
if(pair->cnt.tag->param_off)
(*pair->cnt.tag->param_off)(&(pair->cnt),pair->name);
}
else
{
pair = new_param_pair();
pair->name = name;
pair->next = param_scope_stack[i];
param_scope_stack[i]=pair;
}
if(cnt->tag->param_on)
(*cnt->tag->param_on)(cnt,name);
pair->cnt = *cnt;
pair->global=1;
return 1;
}
/*------------------------------------------------------------------------*/
int gnset_param(name,cnt,delta)
char *name;
struct s_content *cnt;
int delta;
{
struct s_param_pair *pair;
struct s_content *old;
int i;
if(strcmp(name,"$")==0) return 1;
if(param_level<=0) push_param_scope();
if(delta<0)
{zz_error(INTERNAL_ERROR,"gnset_param - bad delta (%d)",delta);return 0;}
if(param_level<=delta)i=0;
else i=param_level-delta-1;
pair = param_scope_stack[i];
// WARNING: linear scan
while(pair && pair->name!=name)pair=pair->next;
if(pair)
{
if(pair->cnt.tag->param_off)
(*pair->cnt.tag->param_off)(&(pair->cnt),pair->name);
}
else
{
pair = new_param_pair();
pair->name = name;
pair->next = param_scope_stack[i];
param_scope_stack[i]=pair;
}
if(cnt->tag->param_on)
(*cnt->tag->param_on)(cnt,name);
pair->cnt = *cnt;
pair->global=0;
return 1;
}
/*------------------------------------------------------------------------*/
int unset_param(char *name)
{
struct s_param_pair *pair,**ptr;
struct s_content *old;
int i;
if(strcmp(name,"$")==0) return 1;
i=param_level-1;
if(i<0) return 0;
ptr= &(param_scope_stack[i]);
while(*ptr && (*ptr)->name!=name) ptr= &((*ptr)->next);
if(*ptr)
{
pair= *ptr;
*ptr = pair->next;
if(pair->cnt.tag->param_off)
(*pair->cnt.tag->param_off)(&(pair->cnt),pair->name);
free_param_pair(pair);
}
return 0;
}
/*------------------------------------------------------------------------*/
/*
scans param scopes downward, looking for a param
whose name is token->value.
if found, token is overwritten, paramname is written
returns 0 if unable to substitute (token!=ident or not found)
returns 1 if local param found
returns 2 if global param found
*/
int param_substitute(struct s_content *token, char **paramname)
{
struct s_param_pair *pair;
struct s_content *cnt;
char *name;
int i;
*paramname=0;
if(token->tag!=tag_ident) return 0;
name = (char*)s_content_value(*token);
pair=0;
for(i=param_level-1;pair==0 && i>=0;i--)
{
pair = param_scope_stack[i];
while(pair && pair->name!=name) pair=pair->next;
}
if(pair)
{
*paramname = name;
cnt = &(pair->cnt);
*token = *cnt;
return pair->global?2:1;
}
else
return 0;
}
/*------------------------------------------------------------------------*/
int local_param_substitute(struct s_content *token, struct s_content *paramname)
{
struct s_param_pair *pair;
struct s_content *cnt;
char *name;
int i;
paramname->tag = tag_none;
if(token->tag!=tag_ident) return 0;
name = (char*)s_content_value(*token);
if(param_level>0)
{
pair = param_scope_stack[param_level-1];
while(pair && pair->name!=name) pair=pair->next;
if(pair)
{
paramname->tag= tag_ident;
/*paramname->value = (long) name; era cosi'*/
s_content_value(*paramname) = (long)name; /*ep*/
cnt = &(pair->cnt);
*token = *cnt;
}
}
return 0;
}
/*------------------------------------------------------------------------*/
int s_param_filter(int argc, struct s_content argv[], struct s_content *ret)
{
struct s_param_pair *pair;
int i,lev;
char *name;
name = (char*)s_content_value(argv[0]);
lev = 0;
pair=0;
for(i=param_level-1;pair==0 && i>=0;i--)
{
pair = param_scope_stack[i];
while(pair && pair->name!=name) pair=pair->next;
}
if(pair && !pair->global)
*ret=pair->cnt;
else
*ret=argv[0];
return 1;
}
/*------------------------------------------------------------------------*/
int list_params(void)
{
struct s_param_pair *pair;
int i,lev;
lev=0;
if(param_level<=0)
{
printz("param stack is empty\n");
return 1;
}
for(i=0;i<param_level;i++)
{
pair = param_scope_stack[i];
while(pair)
{
printz("%3d%c ",i,pair->global?'G':'L');
printz("%-20.20s == %z\n",pair->name,&(pair->cnt));
pair=pair->next;
}
}
return 1;
}
/*---------------------------------------------------------------------------*/
int zz_get_param_stack_depth()
{
return param_level;
}
/*---------------------------------------------------------------------------*/
int show_param_memory(void)
{
PRINTMEM("param",param_mem)
return 0;
}
static char sccsid[]="@(#)param.c 6.2\t11/9/94";
static char rcsid[] = "$Id: param.c,v 1.11 2002/06/03 11:06:13 kibun Exp $ ";