This commit was generated by cvs2svn to track changes on a CVS vendor

branch.
This commit is contained in:
Franck Wajsburt 2002-04-09 12:33:07 +00:00
commit fd71db8218
11 changed files with 1123 additions and 0 deletions

View File

@ -0,0 +1,3 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = doc src

View File

@ -0,0 +1,35 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(src/expy.y)
EXP_MAJOR_VERSION=1
EXP_MINOR_VERSION=0
EXP_VERSION=$EXP_MAJOR_VERSION.$EXP_MINOR_VERSION
AC_SUBST(EXP_MAJOR_VERSION)
AC_SUBST(EXP_MINOR_VERSION)
AC_SUBST(EXP_VERSION)
# For automake.
VERSION=$EXP_VERSION
PACKAGE=exp
dnl Initialize automake stuff
AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
dnl Checks for programs.
AC_PROG_CC
AC_PROG_RANLIB
AM_PROG_LEX
AC_PROG_YACC
AC_PROG_MAKE_SET
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AM_ALLIANCE
AC_OUTPUT([
Makefile
doc/Makefile
src/Makefile
])

View File

@ -0,0 +1,4 @@
## Process this file with automake to produce Makefile.in
man_MANS = exp.1
EXTRA_DIST = $(man_MANS)

328
alliance/src/exp/doc/exp.1 Normal file
View File

@ -0,0 +1,328 @@
.\" ---------------------------------------------------------------------------
.TH EXP 1.0 "March 18, 2002" "UPMC/ASIM/LIP6"
.\" $Id: exp.1,v 1.1 2002/04/09 12:33:07 franck Exp $
.\" @(#)02/02/18 UPMC/ASIM/LIP6; Author: Franck Wajsburt
.\" ---------------------------------------------------------------------------
.\" Main useful commands
.\" --------------------
.\" .TH Head and Foot of page
.\" .SH at the line begining is a Section Header
.\" .SS at the line begining is a Sub-Section Header
.\" .TP <num> allows to present a list of items, the nextline is the title,
.\" the following lines is the corpus shifted of <num> chars.
.\" if <num> is omited, the default value is 7
.\" .so filename allows to include a filename (absolute or relative to MANPATH)
.\" \fB is for Bold font \fP is to return to Previous font
.\" \fI is to underlined or to change to Italic font
.\" .B .I can be used for Bold or Italic, if place a the line beginning
.\" .br at the line begining break the line, a blank line put a blank line
.\" .nf Begins a Non-Formatted zone where each line-break is put as-is
.\" .fi Returns to Formatted mode .nf/.fi is usefull for example to draw tables
.\" ---------------------------------------------------------------------------
.SH EXP
.\" ---------------------------------------------------------------------------
exp - a multiple expession calculator.
.so man1/origin.1
.SH SYNOPSIS
.\" ---------------------------------------------------------------------------
\fBexp\fP [\fB-v\fPn\fI0..4\fP] [\fB-o\fP \fIoutput-file\fP] [\fIinput-file\fP]
.SH DESCRIPTION
.\" ---------------------------------------------------------------------------
Input is an ascii format file including numeric expessions with variables.
Input file can includes other input files thanks to an inclusion directive.
\fBexp\fP reads the input files to write it as is in the output file, but the
numeric expessions are replaced by their value.
.SH OPTIONS
.\" ---------------------------------------------------------------------------
.TP
.B -v
verbose mode
.br
0 : quiet mode
.br
1 : messages \fImess(...)\fP are printed
.br
2 : few statistics
.br
3 : all expressions are decomposed
.br
4 : yacc messages
.TP
.B -o \fIoutput-file\fP
where \fBexp\fP writes (stdout by default).
.TP
.I input-file
where \fBexp\fP reads (stdin by default).
.SH EXP FORMAT FILES
.\" ---------------------------------------------------------------------------
Except the expessionsi and offline comments, the output file is identical to the
flattened view of the input files whatever they are.
The expession forms can be either \fI[expessions]\fP or \fI{expessions}\fP.
The first form is for floating point expessions, the second one is for
integer expessions. By default, the print format is respectively %7.3f
and %4d (cf. \fIsprintf(3)\fP).
Offline comments begins with // and ends at the beginning of the next line.
.I Examples
.IP \(bu 3
[ 3.0 + 12.1] \fIprint\fP 15.100
.IP \(bu 3
{ 3.0 + 12.1} \fIprint\fP 15
.P
It is possible to have more that one expession separated by \fI;\fP
(semi-column). All the expessions of a list are computed, but only the last
one is printed. If the last expession is empty, \fBexp\fP do not print
anything (see Examples section).
.I Examples
.IP \(bu 3
[ 6. *2.0;
.br
3.0 + 12.1 ] \fIprint\fP 15.100
.IP \(bu 3
[ 6. *2.0;
.br
3.0 + 12.1; ] \fIprint\fP nothing
.P
It is possible to have comments in expessions. A comment begins with \fI#\fP
(diese) and ends to the carriage return.
Comment in expression is not copied to the output file.
.I Example
.IP \(bu 3
[ 3.0 + 12.1 # comment
.br
] \fIprint\fP 15.100
.SS Expessions
.\" ----------
Expession is a multi-level numeric expession using numbers, variables,
arithmetic operators and numeric functions.
.I Examples
.IP \(bu 3
[ i=3.0; i*12.1] \fIprint\fP 15.100
.IP \(bu 3
{i=3} \fIprint\fP 3
.br
{i++} \fIprint\fP 4
.P
.SS Arithmetic Operators
.\" --------------------
The operators, in order of increasing priority, are
.TP
.B + -
Addition and subtraction.
.TP
.B * /
Multiplication and division.
.TP
.B ++ --
post-incrementation of 1, post-decrementation of 1.
.TP
.B ( )
Grouping
.TP
.B =
Variable affectation. The return value is the one affected.
.SS Boolean Operators
.\" -----------------
.TP
.B > <
respectively greater than and lower than
.TP
.B def(variable)
True whenever variable is defined yet
.TP
.B ndef(variable)
True whenever variable is not defined yet
.SS Variables
.\" ---------
Expession values may be stored in simple variables.
.\" or one dimension arrays.
There are three forms of variable name.
First, they can begin with a letter followed by any number of letters, digits
and underscores; second, they can begin with \fI"\fP (double quote) followed
by any number of any char and ended by a \fI"\fP; Third they can begin with
\fI\'\fP (quote) then a regular expression (see \fIregex(7)\fP) ended
by \fI\'\fP. \fBexp\fP is case sensitive.
.\" Array index is put between \fI()\fP.
.I Examples
.IP \(bu 3
[ VAR_1=3.0; # first form
.br
"variable numero 2"=12.0; # second form
.br
] \fIprint\fP nothing
.IP \(bu 3
[ VAR_1 * "variable numero 2" ] \fIprint\fP 15.100
.P
When a variable appears in the right member of an affectation, \fBexp\fP
uses its value. If it has never been defined, this causes a fatal error.
If it appears the left member, the first time it is automatically created
and its value is set, or its value is changed.
.SS Special variables
.\" -----------------
\fBfloat_fmt\fP, \fBinteger_fmt\fP and \fBstring_fmt\fP special variables to
redefine print format of floats, integers and strings. Defaults are %7.3f,
%-8s and %4d. Those variables are the only variables with a non numerical
value.
.I Examples
.IP \(bu 3
[\fBfloat_fmt\fP = "%7.1f";] \fIprint\fP nothing
.IP \(bu 3
[ 3.0 + 12.1] \fIprint\fP 15.1
.P
\fBverbose\fP is the variable passed in argument list, which can be modified
by the program itself.
.I Examples \fP get details of expression calculation
.IP \(bu 3
[tmp = \fBverbose\fP; \fBverbose\fP = 3; \fI..expressions..\fP;
.br
\fBverbose\fP = tmp;]
.P
.SS Numeric functions
.\" -----------------
Few numeric functions are available. The form is \fIfun(args)\fP.
The arguments take the form of a list of expessions, separated with a \fI,\fP
(comma). The number of arguments depends on functions.
It is possible to make a list of arguments with a regular expession
(see \fIregex(7)\fP).
Then all matching variable names are part of the list.
.TP
.B min\fI(args)\fP max\fI(args)\fP
The minimum (resp. maximum) value of its arguments.
.I Examples
.RS 7
.IP \(bu 3
[min(3.0,12.1)] \fIprint\fP 3.000
.IP \(bu 3
[min('RW_ALU.*')] \fIprint\fP min value of all variables begining by RW_ALU
.RE
.TP
.B inf\fI(step,val)\fP sup\fI(step,val)\fP
Two arguments. \fPinf\fP (resp. \fPsup\fP) function rounds the second argument
(val) downwards (resp. upwards) to an integer number of the first argument
(step).
.I Examples
.RS 7
.IP \(bu 3
[step=0.3;value=1.6;inf(step,value)] \fIprint\fP 1.500
.RE
.SS Special functions and directives
.\" --------------------------------
.TP
.B if\fI(condition, expr1, expr2, ...)\fP
Calculates the condition if it is true (means greater than zero), the following
expressions are all calculated.
.TP
.B sort\fI(args)\fP rsort\fI(args)\fP
\fBsort\fP (resp. reverse \fBrsort\fP) numerically all its arguments, each
argument must be a variable, not directly a numeric expession. The return
value is the sorted list of its arguments.
.TP
.B message\fI(args)\fP
writes its arguments to stdout using \fIfloat_fmt\fP, one argument per line.
The form is :
\fIvariable_name = value;\fP,
value is omitted if the variable has never been defined.
.br
.I Examples
.RS 7
.IP \(bu 3
[message('"'this is a message'"');] \fIprint\fP
.br
this is a message
.IP \(bu 3
[a1b=0; a2b=1O; a3b=5; message(a*b);] \fIprint\fP
.br
a1b = 0.000
.br
a2b = 1O.000
.br
a3b = 5.000
.IP \(bu 3
[string_fmt=%6s; message(sort(a*b));] \fIprint\fP
.br
a1b = 0.000
.br
a3b = 5.000
.br
a2b = 1O.000
.RE
.TP
\fB#include "filename"\fP
Opens the file in argument then returns to the current file as soon as the new
one is empty.
.SH EXAMPLES
.\" ---------------------------------------------------------------------------
.TP
.B Input file
.nf
# this is a test file
[ # few variables
WITDH = 2;
LENGTH = 25 ;
]
this message is unchanged but all expresions are computed
length_div_2 = [LENGTH/2]
length_mul_2 = {LENGTH*2}
result = [max ('leng.*')]
.fi
.TP
.B Output file
.nf
# this is a test file
this message is unchanged but all expresions are computed
length_div_2 = 12.500
length_mul_2 = 50
result = 12.500
.fi
.SH AUTHOR
Written by Franck Wajsburt.
.SH SEE ALSO
Alliance .rds file uses \fBexp\fP to be generated.
.so man1/bug_report.1

View File

@ -0,0 +1,9 @@
## Process this file with automake to produce Makefile.in
bin_PROGRAMS = exp
YACC = @YACC@ -d -v --debug
CFLAGS = @CFLAGS@ @ALLIANCE_CFLAGS@
exp_LDADD = -lm -lfl
exp_SOURCES = exp.h expy.y expl.l ht.c ht.h main.c

View File

@ -0,0 +1,14 @@
#ifndef _RDS_H_
#define _RDS_H_
#include "ht.h"
extern int yydebug;
extern int yyparse(void);
extern FILE *yyin;
extern FILE *yyout;
extern ht_t * dico;
extern int verbose;
extern char * expfname ;
#endif

111
alliance/src/exp/src/expl.l Normal file
View File

@ -0,0 +1,111 @@
%{
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include "exp.h"
#include "expy.h"
extern int lineno;
#define MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
int lineno_stack[MAX_INCLUDE_DEPTH];
char * fname_stack[MAX_INCLUDE_DEPTH];
int include_stack_ptr = 0;
%}
localcomment [ \t]*\/\/.*\n
comment ([ \t]*[#].*)
regex (\'[^'\n#]+\')
ident ([a-zA-Z][a-zA-Z0-9_]*)|(\"[^"\n#]+\")
number ([0-9]+|([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+))([eE][+\-]?[0-9]+)?
blank [ \t]+
if [iI][fF]
min [mM][iI][nN]
max [mM][aA][xX]
inf [iI][nN][fF]
sup [sS][uU][pP]
sort [sS][oO][rR][tT]
rsort [rR][sS][oO][rR][tT]
def [Dd][Ee][Ff]
ndef [Nn][Dd][Ee][Ff]
include [Ii][Nn][Cc][Ll][Uu][Dd][Ee]
message [Mm][Ee][Ss][Ss][Aa][Gg][Ee]
%x EXP INC
%%
{localcomment} {lineno++;}
[\[\{] {BEGIN(EXP);return *yytext;}
<EXP>[\]}] {BEGIN(INITIAL);return *yytext;}
<INITIAL>\n {lineno++;ECHO;}
<INITIAL>{comment} {ECHO;}
<INITIAL>{include} {BEGIN(INC);}
<INC>{ident} { /* got the include file name */
char * filename = yytext;
if (include_stack_ptr >= MAX_INCLUDE_DEPTH) {
fprintf (stderr, " %-3d %s : Includes nested too deeply\n", lineno, expfname);
exit (1);
}
if (*filename == '"') {
*(filename+yyleng-1)='\0';
filename +=1;
}
if ((yyin = fopen( filename, "r" )) == NULL) {
fprintf (stderr, " %-3d %s : %s cannot be opened\n",
lineno, expfname, filename);
exit (1);
}
include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
lineno_stack[include_stack_ptr] = lineno;
fname_stack[include_stack_ptr++] = expfname;
if ((expfname = strdup (filename)) == NULL) {
fprintf (stderr, " %-3d %s : not enough memory\n", lineno, expfname, filename);
exit (1);
}
lineno = 1;
yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE ) );
BEGIN(INITIAL);
}
<INITIAL><<EOF>> { if ( --include_stack_ptr < 0 )
yyterminate();
else {
yy_delete_buffer (YY_CURRENT_BUFFER );
yy_switch_to_buffer (include_stack[include_stack_ptr] );
expfname = fname_stack[include_stack_ptr];
lineno = lineno_stack[include_stack_ptr];
}
}
<EXP>\n {lineno++;}
<EXP>{comment} {}
<EXP>{if} {return IF;}
<EXP>{min} {return MIN;}
<EXP>{max} {return MAX;}
<EXP>{inf} {return INF;}
<EXP>{sup} {return SUP;}
<EXP>{def} {return DEF;}
<EXP>{ndef} {return NDEF;}
<EXP>{sort} {return SORT;}
<EXP>{rsort} {return RSORT;}
<EXP>{message} {return MESS;}
<EXP>{regex} {
*(yytext+yyleng-1)='\0';
yylval.e=htsetre(dico,yytext+1);
return REGEX;
}
<EXP>{ident} { if (dico==NULL) dico=htinit(10000);
if (*yytext == '"') {
*(yytext+yyleng-1)='\0';
yylval.e=htset(dico,yytext+1);
}
else
yylval.e=htset(dico,yytext);
return IDENT;
}
<EXP>{number} {yylval.f=atof(yytext); return NUMBER;}
<EXP>"++" {return PP;}
<EXP>"--" {return MM;}
<EXP,INC>{blank} {}
<EXP>. {return *yytext;}
. {ECHO;}
%%

192
alliance/src/exp/src/expy.y Normal file
View File

@ -0,0 +1,192 @@
%{
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "exp.h"
#include "ht.h"
#define VERBOSE (int)((htget(dico, "verbose")->VAL.f+EPSILON))
#define EPSILON 0.00001
#define anint(x) floor((x) + 0.5)
#define test_init(i) if (((i)->TYPE==0) && ((pcond==0) || (cond[pcond]>0.))) {\
printf(" %-3d %s : <%s> undefined\n", lineno, expfname, (i)->KEY);\
exit (1);}\
(i)->USED = 1
#define pa(v,e) if (VERBOSE>2) printf("%7.3f -> %s\n",e,v->KEY)
#define pi(e) if (VERBOSE>2) printf("%7.3f <- %s\n",e->VAL.f,e->KEY)
#define pe(s,n) if (VERBOSE>2) printf("%7.3f %s\n",n,s)
#define PCONDMAX 16 /* profondeur de la pile de conditions */
int lineno=1;
char * expfname;
ht_t * dico;
static int pcond=0;
static double cond[PCONDMAX]; /* pile de conditions : +1:vrai, -1:faux */
static char * string_fmt = "%-65s";
static char * float_fmt = "%7.3f";
static char * integer_fmt = "%4d";
static htelt_t * ele;
double limit (int fun, htelt_t * args)
{
htelt_t *ele;
double res;
for (ele = args; ele && ele->TYPE == 0; ele = ele->NEXT);
if (ele == NULL)
{
printf(" %-3d %s : none variable defined\n", lineno, expfname);\
exit (1);
}
res = ele->VAL.f;
for (; ele; ele = ele->NEXT)
if ((ele->TYPE != 0) && (((fun == MAX) && (res < ele->VAL.f)) || ((fun == MIN) && (res > ele->VAL.f))))
res = ele->VAL.f;
eltremove (args);
return res;
}
htelt_t *bsort (int sens, htelt_t * args)
{
htelt_t *ele;
int bubble = 1;
if (args->NEXT) /* au moins de 2 elements dans la liste */
while (bubble)
{
bubble = 0;
for (ele = args; ele->NEXT; ele = ele->NEXT)
if (((sens == SORT) && (((ele->VAL.e)->VAL.f) > (((ele->NEXT)->VAL.e)->VAL.f)))
|| ((sens == RSORT) && (((ele->VAL.e)->VAL.f) < (((ele->NEXT)->VAL.e)->VAL.f)))
|| ((sens == MESS) && (strcmp((ele->VAL.e)->KEY,((ele->NEXT)->VAL.e)->KEY)>0)))
{
htelt_t *tmp = ele->VAL.e;
ele->VAL.e = (ele->NEXT)->VAL.e;
(ele->NEXT)->VAL.e = tmp;
bubble = 1;
}
}
return args;
}
htelt_t *mess (int type, char *fmt, htelt_t * args)
{
htelt_t *ele;
if (VERBOSE)
{
for (ele = args; ele; ele = ele->NEXT)
{
if ((type == MESS) || ((ele->VAL.e)->TYPE == HT_FLOAT))
{
printf (string_fmt, (ele->VAL.e)->KEY);
if ((ele->VAL.e)->TYPE == HT_FLOAT)
{
printf (" = ");
printf (fmt, (ele->VAL.e)->VAL.f);
}
printf ("\n");
}
}
}
eltremove (args);
}
%}
%union
{
htelt_t * e;
double f;
}
%token IF PP MM MAX MIN SUP INF SORT RSORT MESS DEF NDEF
%token <f>NUMBER
%token <e>IDENT REGEX
%type <f>exp cond
%type <e>args idents
%right '='
%right '<' '>'
%left '+' '-'
%left '*' '/'
%%
blocs : /* rien */ { if (VERBOSE>1) htstat(dico); return 1;}
| bloc blocs
;
bloc : '[' exps exp ']' { fprintf (yyout, float_fmt, $3);}
| '{' exps exp '}' { fprintf (yyout, integer_fmt, (int)$3);}
| '[' exp ']' { fprintf (yyout, float_fmt, $2);}
| '{' exp '}' { fprintf (yyout, integer_fmt, (int)$2);}
| '[' SORT '(' idents ')' ']' { mess(SORT,float_fmt, bsort (SORT, $4));}
| '{' SORT '(' idents ')' '}' { mess(SORT,integer_fmt, bsort (SORT, $4));}
| '[' RSORT '(' idents ')' ']' { mess(SORT,float_fmt, bsort (RSORT, $4));}
| '{' RSORT '(' idents ')' '}' { mess(SORT,integer_fmt, bsort (RSORT, $4));}
| '[' MESS '(' idents ')' ']' { mess(MESS,float_fmt, bsort (MESS, $4));}
| '{' MESS '(' idents ')' '}' { mess(MESS,integer_fmt, bsort (MESS, $4));}
| '[' exps ']' { }
| '{' exps '}' { }
;
exps : exp ';' { }
| exps exp ';' { }
;
exp : IDENT '=' exp { if ((pcond==0) || (cond[pcond]>0.)) {
$1->VAL.f=$3; $1->TYPE=HT_FLOAT;
$1->FNAME=expfname; $1->FLINE=lineno;
$$=$3; pa($1,$$);
}
}
| NUMBER { $$ = $1; pe(" ",$$);}
| IDENT { test_init($1); $$ = $1->VAL.f; pi($1);}
| IDENT PP { test_init($1); $$ = $1->VAL.f; $1->VAL.f += 1.0;}
| IDENT MM { test_init($1); $$ = $1->VAL.f; $1->VAL.f -= 1.0;}
| exp '<' exp { $$ = ($1 < $3) ? 1. : -1.; pe(" < ",$$);}
| exp '>' exp { $$ = ($1 > $3) ? 1. : -1.; pe(" > ",$$);}
| exp '+' exp { $$ = $1 + $3; pe(" + ",$$);}
| exp '-' exp { $$ = $1 - $3; pe(" - ",$$);}
| exp '*' exp { $$ = $1 * $3; pe(" * ",$$);}
| exp '/' exp { $$ = $1 / $3; pe(" / ",$$);}
| '(' exp ')' { $$ = $2;}
| '-' exp { $$ = -$2; pe(" - ",$$);}
| IF '(' cond ',' args ')' { for (ele = $5; ele->NEXT; ele = ele->NEXT);
$$ = ele->VAL.f;
pcond--; eltremove ($5);
}
| SUP '(' exp ',' exp ')' { $$ = anint(($5+($3/2)-EPSILON)/$3)*$3; pe(" sup ",$$);}
| INF '(' exp ',' exp ')' { $$ = ((int)(floor(($5+EPSILON)/$3)))*$3; pe(" inf ",$$);}
| MAX '(' args ')' { $$ = limit (MAX, $3); pe(" max ",$$);}
| MIN '(' args ')' { $$ = limit (MIN, $3); pe(" min ",$$);}
| DEF '(' IDENT ')' { $$ = ($3->TYPE==0) ? -1. : +1.; pe($3,$$);}
| NDEF '(' IDENT ')' { $$ = ($3->TYPE==0) ? +1. : -1.; pe($3,$$);}
;
cond : exp { if (pcond < PCONDMAX)
cond[++pcond] = $1;
else
yyerror ("too much conditions")
}
;
idents : IDENT { $$ = eltadd (NULL,NULL); $$->VAL.e=$1;}
| IDENT ',' idents { $$ = eltadd ($3,NULL); $$->VAL.e=$1;}
| REGEX { $$ = $1->NEXT; $1->NEXT=NULL;}
| REGEX ',' idents { $$ = $1->NEXT; $1->NEXT=$3;}
;
args : exp { $$ = eltadd (NULL,NULL); $$->VAL.f=$1; $$->TYPE=HT_FLOAT;pe(" , ",$1);}
| exp ',' args { $$ = eltadd ($3,NULL); $$->VAL.f=$1; $$->TYPE=HT_FLOAT;pe(" , ",$3);}
| REGEX { $$ = $1->NEXT; $1->NEXT=NULL;
for (ele = $$; ele; ele = ele->NEXT)
{
ele->VAL.e->USED = 1;
ele->TYPE = (ele->VAL.e)->TYPE;
ele->VAL.f = (ele->VAL.e)->VAL.f;
}
}
| REGEX ',' args { $$ = $1->NEXT; $1->NEXT=$3;
for (ele = $1; ele; ele = ele->NEXT)
{
ele->VAL.e->USED = 1;
ele->TYPE = (ele->VAL.e)->TYPE;
ele->VAL.f = ele->VAL.e->VAL.f;
}
}
;
%%
int yyerror(char *s)
{
printf(" %-3d %s : %s\n", lineno, expfname, s);
exit (1);
}

244
alliance/src/exp/src/ht.c Normal file
View File

@ -0,0 +1,244 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
#include "ht.h"
/* gestion des entrees du dictionnaire
** =============================================================================
*/
static htelt_t *free_htelt = NULL;
/* ajoute une entree (initialisé à 0) en tete de liste
** ---------------------------------------------------
*/
htelt_t *eltadd (htelt_t * list, char *key)
{
htelt_t *new_elt;
if (free_htelt)
{
new_elt = free_htelt;
free_htelt = free_htelt->NEXT;
}
else if ((new_elt = malloc (sizeof (htelt_t))) == NULL)
{
perror ("add elt in dictionnary");
exit (1);
}
if (key)
if ((new_elt->KEY = strdup (key)) == NULL)
{
perror ("add elt in dictionnary");
exit (1);
}
new_elt->NEXT = list;
new_elt->TYPE = 0;
new_elt->USED = 0;
new_elt->VAL.f = 0.;
return new_elt;
}
/* replace une entree dans la liste des entrees libres
** rend le pointeur NEXT de l'entree effacée
** ---------------------------------------------------
*/
htelt_t *eltdel (htelt_t * list)
{
htelt_t *del_elt = NULL;
if (list)
{
del_elt = list->NEXT;
list->NEXT = free_htelt;
free_htelt = list;
}
return del_elt;
}
/* efface une liste d'elements
** ---------------------------
*/
void eltremove (htelt_t * list)
{
htelt_t *elt;
for (elt = list; elt; elt = eltdel (elt));
}
/* efface le dictionnaire complet
** ------------------------------
*/
void htremove (ht_t * ht)
{
int i;
for (i = 1; i < (int) ht[0]; i++)
eltremove (ht[i]);
free (ht);
}
/* statistiques
** ------------
*/
void htstat (ht_t * ht)
{
int i;
htelt_t *elt;
if (ht)
{
static int start=1;
for (i = 1; i < (int) ht[0]; i++)
for (elt = ht[i]; elt; elt = elt->NEXT)
if (elt->USED == 0)
{
if (start)
{
start=0;
printf ("Warning : following variables declared but never used :\n");
}
printf (" %-3d %-20s : %s\n", elt->FLINE, elt->FNAME, elt->KEY);
}
printf ("\n");
free (ht);
}
}
/* entrees sorties du dictionnaire
** =============================================================================
*/
static int primes[] = {
101, 223, 311, 419, 547, 659, 727, 877, 967,
1061, 2053, 3299, 4391, 5309, 6421, 7069, 8543, 9397,
10337, 20143, 32423, 43151, 52223, 63179, 0
};
/* creation d'un dictionnaire
** --------------------------
*/
ht_t *htinit (int size)
{
int i;
ht_t *ht;
/* prend le premier nombre premier au dela de size */
for (i = 0; primes[i] && (size > primes[i]); i++);
if (primes[i] == 0)
{
fprintf (stderr, "Erreur : hash table trop grande (> %d)\n", primes[i - 1]);
exit (1);
}
size = primes[i];
if ((ht = calloc (size + 1, sizeof (htelt_t *))) == NULL)
{
perror ("htinit");
exit (1);
}
ht[0] = (htelt_t *) size; /* taille de la table dans premiere case */
return ht;
}
/* calcul de la valeur de hachage primaire
** ---------------------------------------
*/
static int hash (ht_t * ht, char *key)
{
int alveole = 0;
int length = strlen (key);
int segment;
int l;
if (ht == NULL)
{
fprintf (stderr, "dictionnary not allocated\n");
exit (1);
}
if ((key == NULL) || (length == 0))
{
fprintf (stderr, "Error : hash (NULL)\n");
exit (1);
}
for (l = 0; l < length; l += 2)
{
segment = 0xFFFF & ((key[l] << 8) | key[l + 1]);
alveole = alveole ^ ((segment << 1) | (segment >> 15));
}
alveole %= (int) ht[0]; /* ht[0] == la taille de la table */
return (alveole + 1); /* +1 car on ne doit rien mettre dans case 0 */
}
/* recherche d'une entree dans la table
** rend un pointeur sur l'element
** htget()->KEY pointe sur la cle key
** htget()->VAL.i contient la valeur int
** htget()->VAL.f contient la valeur double
** htget()->VAL.s contient la valeur char *
** ----------------------------------------
*/
htelt_t *htget (ht_t * ht, char *key)
{
int alveole = hash (ht, key);
htelt_t *p;
for (p = ht[alveole]; p && strcmp (p->KEY, key); p = p->NEXT);
return p;
}
/* ajout d'une nouvelle entree dans la table
** NE VERIFIE PAS SI L'ELEMENT N'EST PAS DEJA PRESENT
** --------------------------------------------------
*/
htelt_t *htadd (ht_t * ht, char *key)
{
int alveole = hash (ht, key);
return ht[alveole] = eltadd (ht[alveole], key);
}
/* recherche d'une entree dans la table et ajout si absente
** --------------------------------------------------------
*/
htelt_t *htset (ht_t * ht, char *key)
{
int alveole = hash (ht, key);
htelt_t *p;
for (p = ht[alveole]; p && strcmp (p->KEY, key); p = p->NEXT);
if (p)
return p;
return ht[alveole] = eltadd (ht[alveole], key);
}
/* recherche d'une regexp dans la table et ajout si absente
** rend un pointeur sur la liste CIRCULAIRE d'element trouves
** NULL sinon
** --------------------------------------------------------
*/
htelt_t *htsetre (ht_t * ht, char *key)
{
regex_t preg;
htelt_t *elt, *res = NULL;
int i;
if (regcomp(&preg, key, REG_EXTENDED | REG_NOSUB) != 0)
return NULL;
if (ht)
for (i = 1; i < (int) ht[0]; i++)
for (elt = ht[i]; elt; elt = elt->NEXT)
if (regexec (&preg, elt->KEY, (size_t) 0, NULL, 0) == 0)
{
if (res)
{
htelt_t * new = eltadd (res->NEXT, NULL);
new->VAL.e = elt;
res->NEXT = new ;
res = new;
}
else
{
res = eltadd (NULL, NULL);
res->NEXT = res;
res->VAL.e = elt;
}
}
regfree (&preg);
return res;
}

95
alliance/src/exp/src/ht.h Normal file
View File

@ -0,0 +1,95 @@
#ifndef _HT_H_
#define _HT_H_
/* declaration de types :
** 1) union de types pour la valeur d'une entree dans le dicionnaire
** 2) type d'une entree
** 3) type du dictionnaire
** -----------------------------------------------------------------
*/
typedef union
{
struct htelt_st *e;
double f;
int i;
char *s;
}
elt_t;
typedef struct htelt_st
{
struct htelt_st * NEXT;
char *KEY;
int TYPE;
int USED;
int FLINE;
char * FNAME;
elt_t VAL;
}
htelt_t;
typedef htelt_t * ht_t;
enum htelt_e {HT_EMPTY, HT_INT, HT_STRING, HT_FLOAT};
/* ajoute une entree (initialisé à 0) en tete de liste
** ---------------------------------------------------
*/
extern htelt_t *eltadd (htelt_t * list, char *key);
/* replace une entree dans la liste des entrees libres
** rend le pointeur NEXT de l'entree effacée
** ---------------------------------------------------
*/
extern htelt_t *eltdel (htelt_t * list);
/* efface une liste d'elements
** ---------------------------
*/
extern void eltremove (htelt_t * list);
/* donne des info sur l'usage du dico
** ----------------------------------
*/
extern void htremove (ht_t * ht);
/* efface le dictionnaire complet
** ------------------------------
*/
extern void htremove (ht_t * ht);
/* creation du dictionnaire
** ------------------------
*/
extern ht_t *htinit (int size);
/* recherche d'une entree dans la table
** rend un pointeur sur l'element
** htget()->KEY pointe sur la cle key
** htget()->VAL.i contient la valeur int
** htget()->VAL.f contient la valeur double
** htget()->VAL.s contient la valeur char *
** ----------------------------------------
*/
extern htelt_t *htget (ht_t * ht, char *key);
/* ajout d'une nouvelle entree dans la table
** NE VERIFIE PAS SI L'ELEMENT N'EST PAS DEJA PRESENT
** --------------------------------------------------
*/
extern htelt_t *htadd (ht_t * ht, char *key);
/* recherche d'une entree dans la table et ajout si absente
** --------------------------------------------------------
*/
htelt_t *htset (ht_t * ht, char *key);
/* recherche d'une regexp dans la table et ajout si absente
** rend un pointeur sur la liste CIRCULAIRE d'elements trouves
** NULL sinon
** --------------------------------------------------------
*/
htelt_t *htsetre (ht_t * ht, char *key);
#endif

View File

@ -0,0 +1,88 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include "exp.h"
#include "ht.h"
void usage (char *av[])
{
printf ("Usage : %s [-h] [-v level] [-o outfile] [infile]\n\n", av[0]);
printf (" -h this help\n");
printf (" -v verbose mode (level is 1:2:3:4)\n");
printf (" -o define the output file (stdout by default)\n");
printf (" infile define the input file (stdin by default)\n");
printf ("\n");
exit (1);
}
void getoption (int ac, char *av[], FILE ** expout, FILE ** expin)
{
char option;
int verbose;
*expin = stdin;
*expout = stdout;
yydebug = 0;
dico=htinit(10000);
htset(dico,"verbose")->VAL.f = -1.0;
htget(dico,"verbose")->TYPE = HT_INT;
htget(dico,"verbose")->USED = 1;
while ((option = getopt (ac, av, "hv:o:")) != EOF)
{
switch (option)
{
case 'v':
verbose = *optarg - '0';
if ((verbose < 0)||(verbose > 9))
usage (av);
yydebug = (verbose == 4) ? 1 : 0;
htset(dico,"verbose")->VAL.f = verbose;
break;
case 'o':
if ((*expout = fopen (optarg, "w")) == NULL)
usage (av);
break;
default:
usage (av);
}
}
if (optind < ac)
{
if ((*expin = fopen (av[optind], "r")) == NULL)
usage (av);
expfname = strdup (av[optind++]);
}
if (optind < ac)
usage (av);
}
int main (int ac, char *av[])
{
getoption (ac, av, &yyout, &yyin);
if (htget(dico,"verbose")->VAL.f != 0)
{
puts(" ");
puts(" @@@@@ @@@@ @@@ @@@ @@@");
puts(" @ @ @@ @ @@@ @@");
puts(" @@ @@ @@ @ @@ @@");
puts(" @@@@@@@@@ @@@ @@ @@");
puts(" @@ @@@ @@ @@");
puts(" @@ @ @ @@ @@ @@");
puts(" @@ @@ @ @@ @@@ @@");
puts(" @@@@ @@@ @@@@ @@ @@@");
puts(" @@");
puts(" @@@@");
puts(" ");
puts(" multiple expressions calculator");
puts(" ");
printf(" Alliance CAD System %-4s exp %-3s\n",
ALLIANCE_VERSION, VERSION);
puts(" Copyright (c) 2002, ASIM/LIP6/UPMC");
puts(" E-mail support: alliance-support@asim.lip6.fr");
puts(" ");
}
yyparse ();
return 0;
}