mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-23 19:23:02 +00:00
examples: add a complete example with all the bells and whistles
* examples/c/bistromathic/Makefile, * examples/c/bistromathic/README.md, * examples/c/bistromathic/bistromathic.test, * examples/c/bistromathic/local.mk, * examples/c/bistromathic/parse.y, * examples/c/bistromathic/scan.l: New. * Makefile.am (AM_YFLAGS_WITH_LINES): Add -Wdangling-alias. * examples/test: Make failure errors easier to read.
This commit is contained in:
@@ -42,7 +42,7 @@ dependencies = $(BISON_IN) $(src_bison_SOURCES) $(dist_skeletons_DATA)
|
|||||||
BISON = $(top_builddir)/tests/bison
|
BISON = $(top_builddir)/tests/bison
|
||||||
BISON_IN = $(top_srcdir)/tests/bison.in
|
BISON_IN = $(top_srcdir)/tests/bison.in
|
||||||
YACC = $(BISON) -o y.tab.c
|
YACC = $(BISON) -o y.tab.c
|
||||||
AM_YFLAGS_WITH_LINES = --defines -Werror -Wall --report=all
|
AM_YFLAGS_WITH_LINES = --defines -Werror -Wall,dangling-alias --report=all
|
||||||
AM_YFLAGS = $(AM_YFLAGS_WITH_LINES) --no-lines
|
AM_YFLAGS = $(AM_YFLAGS_WITH_LINES) --no-lines
|
||||||
|
|
||||||
# Initialization before completion by local.mk's.
|
# Initialization before completion by local.mk's.
|
||||||
|
|||||||
@@ -48,6 +48,14 @@ until the input is drained.
|
|||||||
This example is a straightforward conversion of the 'calc' example to the
|
This example is a straightforward conversion of the 'calc' example to the
|
||||||
push-parser model.
|
push-parser model.
|
||||||
|
|
||||||
|
## bistromathic - all the bells and whistles
|
||||||
|
This example demonstrates the best practices when using Bison.
|
||||||
|
- Its interface is pure.
|
||||||
|
- It uses a custom syntax error with location tracking, lookahead correction
|
||||||
|
and token internationalization.
|
||||||
|
- It enables debug trace support with formatting of semantic values.
|
||||||
|
|
||||||
|
It also uses Flex to generate the scanner.
|
||||||
|
|
||||||
<!---
|
<!---
|
||||||
|
|
||||||
@@ -65,6 +73,8 @@ Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
|||||||
Texts. A copy of the license is included in the "GNU Free
|
Texts. A copy of the license is included in the "GNU Free
|
||||||
Documentation License" file as part of this distribution.
|
Documentation License" file as part of this distribution.
|
||||||
|
|
||||||
# LocalWords: mfcalc calc parsers yy rpcalc lexcalc redux reccalc ispell
|
LocalWords: mfcalc calc parsers yy rpcalc lexcalc redux reccalc ispell
|
||||||
# LocalWords: reentrant tokenized american postfix
|
LocalWords: reentrant tokenized american postfix pushcalc bistromathic
|
||||||
--->
|
LocalWords: lookahead
|
||||||
|
|
||||||
|
-->
|
||||||
|
|||||||
35
examples/c/bistromathic/Makefile
Normal file
35
examples/c/bistromathic/Makefile
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# This Makefile is designed to be simple and readable. It does not
|
||||||
|
# aim at portability. It requires GNU Make.
|
||||||
|
|
||||||
|
BASE = bistromathic
|
||||||
|
BISON = bison
|
||||||
|
FLEX = flex
|
||||||
|
XSLTPROC = xsltproc
|
||||||
|
|
||||||
|
all: $(BASE)
|
||||||
|
|
||||||
|
%.c %.h %.xml %.gv: %.y
|
||||||
|
$(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $<
|
||||||
|
|
||||||
|
%.c: %.l
|
||||||
|
$(FLEX) $(FLEXFLAGS) -o$*.c $<
|
||||||
|
|
||||||
|
scan.o: parse.h
|
||||||
|
$(BASE): parse.o scan.o
|
||||||
|
$(CC) $(CFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
run: $(BASE)
|
||||||
|
@echo "Type bistromathic expressions. Quit with ctrl-d."
|
||||||
|
./$<
|
||||||
|
|
||||||
|
html: $(BASE).html
|
||||||
|
%.html: %.xml
|
||||||
|
$(XSLTPROC) $(XSLTPROCFLAGS) -o $@ $$($(BISON) --print-datadir)/xslt/xml2xhtml.xsl $<
|
||||||
|
|
||||||
|
CLEANFILES = \
|
||||||
|
$(BASE) *.o \
|
||||||
|
parse.[ch] parse.output parse.xml parse.html parse.gv \
|
||||||
|
scan.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(CLEANFILES)
|
||||||
32
examples/c/bistromathic/README.md
Normal file
32
examples/c/bistromathic/README.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# bistromathic - all the bells and whistles
|
||||||
|
This example demonstrates the best practices when using Bison.
|
||||||
|
- Its interface is pure.
|
||||||
|
- It uses a custom syntax error with location tracking, lookahead correction
|
||||||
|
and token internationalization.
|
||||||
|
- It enables debug trace support with formatting of semantic values.
|
||||||
|
|
||||||
|
It also uses Flex to generate the scanner.
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Local Variables:
|
||||||
|
fill-column: 76
|
||||||
|
ispell-dictionary: "american"
|
||||||
|
End:
|
||||||
|
|
||||||
|
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of Bison, the GNU Compiler Compiler.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--->
|
||||||
48
examples/c/bistromathic/bistromathic.test
Executable file
48
examples/c/bistromathic/bistromathic.test
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
# Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
1+2*3
|
||||||
|
EOF
|
||||||
|
run 0 7
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
(1+2) * 3
|
||||||
|
EOF
|
||||||
|
run 0 9
|
||||||
|
run -noerr 0 9 -p
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
a = 256
|
||||||
|
sqrt (a)
|
||||||
|
EOF
|
||||||
|
run 0 '256
|
||||||
|
16'
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
a = .16
|
||||||
|
b = 10 ^ 2
|
||||||
|
sqrt (a * b)
|
||||||
|
EOF
|
||||||
|
run 0 '0.16
|
||||||
|
100
|
||||||
|
4'
|
||||||
|
|
||||||
|
cat >input <<EOF
|
||||||
|
*
|
||||||
|
EOF
|
||||||
|
run 0 "err: 1.1: syntax error expected end of file or - or ( or end of line or double precision number or function or variable before *"
|
||||||
36
examples/c/bistromathic/local.mk
Normal file
36
examples/c/bistromathic/local.mk
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
## Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
##
|
||||||
|
## This program is free software: you can redistribute it and/or modify
|
||||||
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
## the Free Software Foundation, either version 3 of the License, or
|
||||||
|
## (at your option) any later version.
|
||||||
|
##
|
||||||
|
## This program 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 General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License
|
||||||
|
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
bistromathicdir = $(docdir)/%D%
|
||||||
|
|
||||||
|
## --------------- ##
|
||||||
|
## Bistromathics. ##
|
||||||
|
## --------------- ##
|
||||||
|
|
||||||
|
if FLEX_WORKS
|
||||||
|
check_PROGRAMS += %D%/bistromathic
|
||||||
|
TESTS += %D%/bistromathic.test
|
||||||
|
EXTRA_DIST += %D%/bistromathic.test
|
||||||
|
nodist_%C%_bistromathic_SOURCES = %D%/parse.y %D%/parse.h %D%/scan.l
|
||||||
|
%D%/calc.c: $(dependencies)
|
||||||
|
|
||||||
|
# Don't use gnulib's system headers.
|
||||||
|
%C%_bistromathic_CPPFLAGS = -I$(top_srcdir)/%D% -I$(top_builddir)/%D%
|
||||||
|
%C%_bistromathic_LDADD = -lm
|
||||||
|
endif FLEX_WORKS
|
||||||
|
|
||||||
|
dist_bistromathic_DATA = %D%/parse.y %D%/scan.l %D%/Makefile %D%/README.md
|
||||||
|
CLEANFILES += %D%/parse.[ch] %D%/scan.c %D%/parse.output
|
||||||
|
CLEANDIRS += %D%/*.dSYM
|
||||||
225
examples/c/bistromathic/parse.y
Normal file
225
examples/c/bistromathic/parse.y
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
%require "3.6"
|
||||||
|
|
||||||
|
%code top {
|
||||||
|
#include <ctype.h> // isdigit
|
||||||
|
#include <math.h> // cos, sin, etc.
|
||||||
|
#include <stddef.h> // ptrdiff_t
|
||||||
|
#include <stdio.h> // printf
|
||||||
|
#include <string.h> // strcmp
|
||||||
|
}
|
||||||
|
|
||||||
|
%code requires {
|
||||||
|
// Function type.
|
||||||
|
typedef double (func_t) (double);
|
||||||
|
|
||||||
|
// Data type for links in the chain of symbols.
|
||||||
|
typedef struct symrec symrec;
|
||||||
|
struct symrec
|
||||||
|
{
|
||||||
|
char *name; // name of symbol
|
||||||
|
int type; // type of symbol: either VAR or FUN
|
||||||
|
union
|
||||||
|
{
|
||||||
|
double var; // value of a VAR
|
||||||
|
func_t *fun; // value of a FUN
|
||||||
|
} value;
|
||||||
|
symrec *next; // link field
|
||||||
|
};
|
||||||
|
|
||||||
|
symrec *putsym (char const *name, int sym_type);
|
||||||
|
symrec *getsym (char const *name);
|
||||||
|
}
|
||||||
|
|
||||||
|
%code provides {
|
||||||
|
#define YY_DECL \
|
||||||
|
int yylex (YYSTYPE *yylval, YYLTYPE *yylloc)
|
||||||
|
YY_DECL;
|
||||||
|
|
||||||
|
void yyerror (YYLTYPE *yylloc, char const *);
|
||||||
|
}
|
||||||
|
|
||||||
|
%code {
|
||||||
|
#define N_
|
||||||
|
#define _
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't share global variables between the scanner and the parser.
|
||||||
|
%define api.pure full
|
||||||
|
|
||||||
|
// To avoid name clashes (e.g., with C's EOF) prefix token definitions
|
||||||
|
// with TOK_ (e.g., TOK_EOF).
|
||||||
|
%define api.token.prefix {TOK_}
|
||||||
|
|
||||||
|
// Customized syntax error messages (see yyreport_syntax_error).
|
||||||
|
%define parse.error custom
|
||||||
|
|
||||||
|
// with locations.
|
||||||
|
%locations
|
||||||
|
|
||||||
|
// and acurate list of expected tokens.
|
||||||
|
%define parse.lac full
|
||||||
|
|
||||||
|
// Generate the parser description file (calc.output).
|
||||||
|
%verbose
|
||||||
|
|
||||||
|
// Generate YYSTYPE from the types assigned to symbols.
|
||||||
|
%define api.value.type union
|
||||||
|
%token
|
||||||
|
PLUS "+"
|
||||||
|
MINUS "-"
|
||||||
|
STAR "*"
|
||||||
|
SLASH "/"
|
||||||
|
CARET "^"
|
||||||
|
LPAREN "("
|
||||||
|
RPAREN ")"
|
||||||
|
EQUAL "="
|
||||||
|
EOL _("end of line")
|
||||||
|
EOF 0 _("end of file")
|
||||||
|
<double>
|
||||||
|
NUM _("double precision number")
|
||||||
|
<symrec*>
|
||||||
|
FUN _("function")
|
||||||
|
VAR _("variable")
|
||||||
|
|
||||||
|
%nterm <double> exp
|
||||||
|
|
||||||
|
// Enable run-time traces (yydebug).
|
||||||
|
%define parse.trace
|
||||||
|
|
||||||
|
// Formatting semantic values in debug traces.
|
||||||
|
%printer { fprintf (yyo, "%s", $$->name); } VAR;
|
||||||
|
%printer { fprintf (yyo, "%s()", $$->name); } FUN;
|
||||||
|
%printer { fprintf (yyo, "%g", $$); } <double>;
|
||||||
|
|
||||||
|
|
||||||
|
// Precedence (from lowest to highest) and associativity.
|
||||||
|
%precedence "="
|
||||||
|
%left "+" "-"
|
||||||
|
%left "*" "/"
|
||||||
|
%precedence NEG // negation--unary minus
|
||||||
|
%right "^" // exponentiation
|
||||||
|
|
||||||
|
%% // The grammar follows.
|
||||||
|
input:
|
||||||
|
%empty
|
||||||
|
| input line
|
||||||
|
;
|
||||||
|
|
||||||
|
line:
|
||||||
|
EOL
|
||||||
|
| exp EOL { printf ("%.10g\n", $1); }
|
||||||
|
| error EOL { yyerrok; }
|
||||||
|
;
|
||||||
|
|
||||||
|
exp:
|
||||||
|
NUM
|
||||||
|
| VAR { $$ = $1->value.var; }
|
||||||
|
| VAR "=" exp { $$ = $3; $1->value.var = $3; }
|
||||||
|
| FUN "(" exp ")" { $$ = $1->value.fun ($3); }
|
||||||
|
| exp "+" exp { $$ = $1 + $3; }
|
||||||
|
| exp "-" exp { $$ = $1 - $3; }
|
||||||
|
| exp "*" exp { $$ = $1 * $3; }
|
||||||
|
| exp "/" exp
|
||||||
|
{
|
||||||
|
if ($3 == 0)
|
||||||
|
{
|
||||||
|
yyerror (&@$, "division by zero");
|
||||||
|
YYERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$$ = $1 / $3;
|
||||||
|
}
|
||||||
|
| "-" exp %prec NEG { $$ = -$2; }
|
||||||
|
| exp "^" exp { $$ = pow ($1, $3); }
|
||||||
|
| "(" exp ")" { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
// End of grammar.
|
||||||
|
%%
|
||||||
|
|
||||||
|
struct init
|
||||||
|
{
|
||||||
|
char const *name;
|
||||||
|
func_t *fun;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct init const funs[] =
|
||||||
|
{
|
||||||
|
{ "atan", atan },
|
||||||
|
{ "cos", cos },
|
||||||
|
{ "exp", exp },
|
||||||
|
{ "ln", log },
|
||||||
|
{ "sin", sin },
|
||||||
|
{ "sqrt", sqrt },
|
||||||
|
{ 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// The symbol table: a chain of 'struct symrec'.
|
||||||
|
static symrec *sym_table;
|
||||||
|
|
||||||
|
// Put functions in table.
|
||||||
|
static void
|
||||||
|
init_table (void)
|
||||||
|
{
|
||||||
|
for (int i = 0; funs[i].name; i++)
|
||||||
|
{
|
||||||
|
symrec *ptr = putsym (funs[i].name, TOK_FUN);
|
||||||
|
ptr->value.fun = funs[i].fun;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
symrec *
|
||||||
|
putsym (char const *name, int sym_type)
|
||||||
|
{
|
||||||
|
symrec *res = (symrec *) malloc (sizeof (symrec));
|
||||||
|
res->name = strdup (name);
|
||||||
|
res->type = sym_type;
|
||||||
|
res->value.var = 0; // Set value to 0 even if fun.
|
||||||
|
res->next = sym_table;
|
||||||
|
sym_table = res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
symrec *
|
||||||
|
getsym (char const *name)
|
||||||
|
{
|
||||||
|
for (symrec *p = sym_table; p; p = p->next)
|
||||||
|
if (strcmp (p->name, name) == 0)
|
||||||
|
return p;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
yyreport_syntax_error (const yyparse_context_t *ctx)
|
||||||
|
{
|
||||||
|
enum { ARGMAX = 10 };
|
||||||
|
int arg[ARGMAX];
|
||||||
|
int n = yysyntax_error_arguments (ctx, arg, ARGMAX);
|
||||||
|
if (n == -2)
|
||||||
|
return 2;
|
||||||
|
YY_LOCATION_PRINT (stderr, *yyparse_context_location (ctx));
|
||||||
|
fprintf (stderr, ": syntax error");
|
||||||
|
for (int i = 1; i < n; ++i)
|
||||||
|
fprintf (stderr, " %s %s",
|
||||||
|
i == 1 ? "expected" : "or", yysymbol_name (arg[i]));
|
||||||
|
if (n)
|
||||||
|
fprintf (stderr, " before %s", yysymbol_name (arg[0]));
|
||||||
|
fprintf (stderr, "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by yyparse on error.
|
||||||
|
void yyerror (YYLTYPE *loc, char const *s)
|
||||||
|
{
|
||||||
|
YY_LOCATION_PRINT (stderr, *loc);
|
||||||
|
fprintf (stderr, ": %s\n", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char const* argv[])
|
||||||
|
{
|
||||||
|
// Enable parse traces on option -p.
|
||||||
|
if (argc == 2 && strcmp(argv[1], "-p") == 0)
|
||||||
|
yydebug = 1;
|
||||||
|
init_table ();
|
||||||
|
return yyparse ();
|
||||||
|
}
|
||||||
61
examples/c/bistromathic/scan.l
Normal file
61
examples/c/bistromathic/scan.l
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/* Prologue (directives). -*- C -*- */
|
||||||
|
|
||||||
|
/* Disable Flex features we don't need, to avoid warnings. */
|
||||||
|
%option nodefault noinput nounput noyywrap
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <errno.h> /* errno, ERANGE */
|
||||||
|
#include <limits.h> /* INT_MIN */
|
||||||
|
#include <stdlib.h> /* strtol */
|
||||||
|
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
|
// Each time a rule is matched, advance the end cursor/position.
|
||||||
|
#define YY_USER_ACTION \
|
||||||
|
yylloc->last_column += yyleng;
|
||||||
|
%}
|
||||||
|
|
||||||
|
%%
|
||||||
|
%{
|
||||||
|
// Each time yylex is called, move the head position to the end one.
|
||||||
|
yylloc->first_line = yylloc->last_line;
|
||||||
|
yylloc->first_column = yylloc->last_column;
|
||||||
|
%}
|
||||||
|
/* Rules. */
|
||||||
|
|
||||||
|
"+" return TOK_PLUS;
|
||||||
|
"-" return TOK_MINUS;
|
||||||
|
"*" return TOK_STAR;
|
||||||
|
"/" return TOK_SLASH;
|
||||||
|
"^" return TOK_CARET;
|
||||||
|
|
||||||
|
"(" return TOK_LPAREN;
|
||||||
|
")" return TOK_RPAREN;
|
||||||
|
|
||||||
|
"=" return TOK_EQUAL;
|
||||||
|
|
||||||
|
/* Scan an identifier. */
|
||||||
|
[a-z]+ {
|
||||||
|
symrec *s = getsym (yytext);
|
||||||
|
if (!s)
|
||||||
|
s = putsym (yytext, TOK_VAR);
|
||||||
|
yylval->TOK_VAR = s;
|
||||||
|
return s->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scan a double precision number. */
|
||||||
|
[0-9]+(\.[0-9]*)?|(\.[0-9]+) {
|
||||||
|
sscanf (yytext, "%lf", &yylval->TOK_NUM);
|
||||||
|
return TOK_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
"\n" yylloc->last_line++; yylloc->last_column = 1; return TOK_EOL;
|
||||||
|
|
||||||
|
/* Ignore white spaces. */
|
||||||
|
[ \t]+ continue;
|
||||||
|
|
||||||
|
<<EOF>> return TOK_EOF;
|
||||||
|
|
||||||
|
. yyerror (yylloc, "syntax error, invalid character");
|
||||||
|
%%
|
||||||
|
/* Epilogue (C code). */
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
cdir = $(docdir)/%D%
|
cdir = $(docdir)/%D%
|
||||||
dist_c_DATA = %D%/README.md
|
dist_c_DATA = %D%/README.md
|
||||||
|
|
||||||
|
include %D%/bistromathic/local.mk
|
||||||
include %D%/calc/local.mk
|
include %D%/calc/local.mk
|
||||||
include %D%/lexcalc/local.mk
|
include %D%/lexcalc/local.mk
|
||||||
include %D%/mfcalc/local.mk
|
include %D%/mfcalc/local.mk
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ run ()
|
|||||||
if test "$out_eff" = "$out_exp"; then
|
if test "$out_eff" = "$out_exp"; then
|
||||||
echo "$me: PASS: $number"
|
echo "$me: PASS: $number"
|
||||||
else
|
else
|
||||||
echo "$me: FAIL: $number (expected output: $out_exp, effective: $out_eff)"
|
echo "$me: FAIL: $number"
|
||||||
|
echo "$me: expected output: $out_exp"
|
||||||
|
echo "$me: effective output: $out_eff"
|
||||||
cat err_eff
|
cat err_eff
|
||||||
exit=false
|
exit=false
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user