importing exp (calculator for .rds files)
This commit is contained in:
parent
cfbe7b858e
commit
930a17fd08
|
@ -0,0 +1,3 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
SUBDIRS = doc src
|
|
@ -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
|
||||||
|
])
|
|
@ -0,0 +1,4 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
man_MANS = exp.1
|
||||||
|
EXTRA_DIST = $(man_MANS)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;}
|
||||||
|
%%
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue