sh: Import arithmetic expression code from dash.
New features: * proper lazy evaluation of || and && * ?: ternary operator * executable is considerably smaller (8K on i386) because lex and yacc are no longer used Differences from dash: * arith_t instead of intmax_t * imaxdiv() not used * unset or null variables default to 0 * let/exp builtin (undocumented, will probably be removed later) Obtained from: dash
This commit is contained in:
parent
0d8d37212b
commit
6262b84eee
@ -3,22 +3,22 @@
|
||||
|
||||
PROG= sh
|
||||
INSTALLFLAGS= -S
|
||||
SHSRCS= alias.c arith.y arith_lex.l cd.c echo.c error.c eval.c exec.c expand.c \
|
||||
SHSRCS= alias.c arith_yacc.c arith_yylex.c cd.c echo.c error.c eval.c \
|
||||
exec.c expand.c \
|
||||
histedit.c input.c jobs.c kill.c mail.c main.c memalloc.c miscbltin.c \
|
||||
mystring.c options.c output.c parser.c printf.c redir.c show.c \
|
||||
test.c trap.c var.c
|
||||
GENSRCS= builtins.c init.c nodes.c syntax.c
|
||||
GENHDRS= builtins.h nodes.h syntax.h token.h
|
||||
SRCS= ${SHSRCS} ${GENSRCS} ${GENHDRS} y.tab.h
|
||||
SRCS= ${SHSRCS} ${GENSRCS} ${GENHDRS}
|
||||
|
||||
# MLINKS for Shell built in commands for which there are no userland
|
||||
# utilities of the same name are handled with the associated manpage,
|
||||
# builtin.1 in share/man/man1/.
|
||||
|
||||
DPADD= ${LIBL} ${LIBEDIT} ${LIBTERMCAP}
|
||||
LDADD= -ll -ledit -ltermcap
|
||||
DPADD= ${LIBEDIT} ${LIBTERMCAP}
|
||||
LDADD= -ledit -ltermcap
|
||||
|
||||
LFLAGS= -8 # 8-bit lex scanner for arithmetic
|
||||
CFLAGS+=-DSHELL -I. -I${.CURDIR}
|
||||
# for debug:
|
||||
# DEBUG_FLAGS+= -g -DDEBUG=2 -fno-inline
|
||||
|
@ -34,8 +34,6 @@
|
||||
|
||||
#define DIGITS(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
|
||||
|
||||
extern const char *arith_buf, *arith_startbuf;
|
||||
|
||||
arith_t arith(const char *);
|
||||
void arith_lex_reset(void);
|
||||
int expcmd(int, char **);
|
||||
|
366
bin/sh/arith.y
366
bin/sh/arith.y
@ -1,366 +0,0 @@
|
||||
%{
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "arith.h"
|
||||
#include "shell.h"
|
||||
#include "var.h"
|
||||
%}
|
||||
%union {
|
||||
arith_t l_value;
|
||||
char* s_value;
|
||||
}
|
||||
%token <l_value> ARITH_NUM ARITH_LPAREN ARITH_RPAREN
|
||||
%token <s_value> ARITH_VAR
|
||||
|
||||
%type <l_value> expr
|
||||
%right ARITH_ASSIGN
|
||||
%right ARITH_ADDASSIGN ARITH_SUBASSIGN
|
||||
%right ARITH_MULASSIGN ARITH_DIVASSIGN ARITH_REMASSIGN
|
||||
%right ARITH_RSHASSIGN ARITH_LSHASSIGN
|
||||
%right ARITH_BANDASSIGN ARITH_BXORASSIGN ARITH_BORASSIGN
|
||||
%left ARITH_OR
|
||||
%left ARITH_AND
|
||||
%left ARITH_BOR
|
||||
%left ARITH_BXOR
|
||||
%left ARITH_BAND
|
||||
%left ARITH_EQ ARITH_NE
|
||||
%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
|
||||
%left ARITH_LSHIFT ARITH_RSHIFT
|
||||
%left ARITH_ADD ARITH_SUB
|
||||
%left ARITH_MUL ARITH_DIV ARITH_REM
|
||||
%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
|
||||
%%
|
||||
|
||||
exp:
|
||||
expr
|
||||
{
|
||||
*YYPARSE_PARAM = $1;
|
||||
return (0);
|
||||
}
|
||||
;
|
||||
|
||||
expr:
|
||||
ARITH_LPAREN expr ARITH_RPAREN
|
||||
{ $$ = $2; } |
|
||||
expr ARITH_OR expr
|
||||
{ $$ = $1 || $3; } |
|
||||
expr ARITH_AND expr
|
||||
{ $$ = $1 && $3; } |
|
||||
expr ARITH_BOR expr
|
||||
{ $$ = $1 | $3; } |
|
||||
expr ARITH_BXOR expr
|
||||
{ $$ = $1 ^ $3; } |
|
||||
expr ARITH_BAND expr
|
||||
{ $$ = $1 & $3; } |
|
||||
expr ARITH_EQ expr
|
||||
{ $$ = $1 == $3; } |
|
||||
expr ARITH_GT expr
|
||||
{ $$ = $1 > $3; } |
|
||||
expr ARITH_GE expr
|
||||
{ $$ = $1 >= $3; } |
|
||||
expr ARITH_LT expr
|
||||
{ $$ = $1 < $3; } |
|
||||
expr ARITH_LE expr
|
||||
{ $$ = $1 <= $3; } |
|
||||
expr ARITH_NE expr
|
||||
{ $$ = $1 != $3; } |
|
||||
expr ARITH_LSHIFT expr
|
||||
{ $$ = $1 << $3; } |
|
||||
expr ARITH_RSHIFT expr
|
||||
{ $$ = $1 >> $3; } |
|
||||
expr ARITH_ADD expr
|
||||
{ $$ = $1 + $3; } |
|
||||
expr ARITH_SUB expr
|
||||
{ $$ = $1 - $3; } |
|
||||
expr ARITH_MUL expr
|
||||
{ $$ = $1 * $3; } |
|
||||
expr ARITH_DIV expr
|
||||
{
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
$$ = $1 / $3;
|
||||
} |
|
||||
expr ARITH_REM expr
|
||||
{
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
$$ = $1 % $3;
|
||||
} |
|
||||
ARITH_NOT expr
|
||||
{ $$ = !($2); } |
|
||||
ARITH_BNOT expr
|
||||
{ $$ = ~($2); } |
|
||||
ARITH_SUB expr %prec ARITH_UNARYMINUS
|
||||
{ $$ = -($2); } |
|
||||
ARITH_ADD expr %prec ARITH_UNARYPLUS
|
||||
{ $$ = $2; } |
|
||||
ARITH_NUM |
|
||||
ARITH_VAR
|
||||
{
|
||||
char *p;
|
||||
arith_t arith_val;
|
||||
char *str_val;
|
||||
|
||||
if (lookupvar($1) == NULL)
|
||||
setvarsafe($1, "0", 0);
|
||||
str_val = lookupvar($1);
|
||||
arith_val = strtoarith_t(str_val, &p, 0);
|
||||
/*
|
||||
* Conversion is successful only in case
|
||||
* we've converted _all_ characters.
|
||||
*/
|
||||
if (*p != '\0')
|
||||
yyerror("variable conversion error");
|
||||
$$ = arith_val;
|
||||
} |
|
||||
ARITH_VAR ARITH_ASSIGN expr
|
||||
{
|
||||
if (arith_assign($1, $3) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = $3;
|
||||
} |
|
||||
ARITH_VAR ARITH_ADDASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) + $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_SUBASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) - $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_MULASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) * $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_DIVASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
|
||||
value = atoarith_t(lookupvar($1)) / $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_REMASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
if ($3 == 0)
|
||||
yyerror("division by zero");
|
||||
|
||||
value = atoarith_t(lookupvar($1)) % $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_RSHASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) >> $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_LSHASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) << $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_BANDASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) & $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_BXORASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) ^ $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} |
|
||||
ARITH_VAR ARITH_BORASSIGN expr
|
||||
{
|
||||
arith_t value;
|
||||
|
||||
value = atoarith_t(lookupvar($1)) | $3;
|
||||
if (arith_assign($1, value) != 0)
|
||||
yyerror("variable assignment error");
|
||||
$$ = value;
|
||||
} ;
|
||||
%%
|
||||
#include "error.h"
|
||||
#include "output.h"
|
||||
#include "memalloc.h"
|
||||
|
||||
#define YYPARSE_PARAM_TYPE arith_t *
|
||||
#define YYPARSE_PARAM result
|
||||
|
||||
const char *arith_buf, *arith_startbuf;
|
||||
|
||||
int yylex(void);
|
||||
int yyparse(YYPARSE_PARAM_TYPE);
|
||||
|
||||
static int
|
||||
arith_assign(char *name, arith_t value)
|
||||
{
|
||||
char *str;
|
||||
int ret;
|
||||
|
||||
str = (char *)ckmalloc(DIGITS(value));
|
||||
sprintf(str, ARITH_FORMAT_STR, value);
|
||||
ret = setvarsafe(name, str, 0);
|
||||
free(str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
arith_t
|
||||
arith(const char *s)
|
||||
{
|
||||
arith_t result;
|
||||
struct stackmark smark;
|
||||
|
||||
setstackmark(&smark);
|
||||
arith_buf = arith_startbuf = s;
|
||||
|
||||
INTOFF;
|
||||
yyparse(&result);
|
||||
arith_lex_reset(); /* Reprime lex. */
|
||||
INTON;
|
||||
|
||||
popstackmark(&smark);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
yyerror(const char *s)
|
||||
{
|
||||
|
||||
yyerrok;
|
||||
yyclearin;
|
||||
arith_lex_reset(); /* Reprime lex. */
|
||||
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* The exp(1) builtin.
|
||||
*/
|
||||
int
|
||||
expcmd(int argc, char **argv)
|
||||
{
|
||||
const char *p;
|
||||
char *concat;
|
||||
char **ap;
|
||||
arith_t i;
|
||||
|
||||
if (argc > 1) {
|
||||
p = argv[1];
|
||||
if (argc > 2) {
|
||||
/*
|
||||
* Concatenate arguments.
|
||||
*/
|
||||
STARTSTACKSTR(concat);
|
||||
ap = argv + 2;
|
||||
for (;;) {
|
||||
while (*p)
|
||||
STPUTC(*p++, concat);
|
||||
if ((p = *ap++) == NULL)
|
||||
break;
|
||||
STPUTC(' ', concat);
|
||||
}
|
||||
STPUTC('\0', concat);
|
||||
p = grabstackstr(concat);
|
||||
}
|
||||
} else
|
||||
p = "";
|
||||
|
||||
i = arith(p);
|
||||
|
||||
out1fmt(ARITH_FORMAT_STR "\n", i);
|
||||
return !i;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
#ifdef TEST_ARITH
|
||||
#include <stdio.h>
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
printf("%d\n", exp(argv[1]));
|
||||
}
|
||||
|
||||
error(const char *s)
|
||||
{
|
||||
fprintf(stderr, "exp: %s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
@ -1,143 +0,0 @@
|
||||
%{
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "arith.h"
|
||||
#include "shell.h"
|
||||
#include "y.tab.h"
|
||||
#include "error.h"
|
||||
#include "memalloc.h"
|
||||
#include "var.h"
|
||||
|
||||
int yylex(void);
|
||||
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,result,max) \
|
||||
do { \
|
||||
result = strnlen(arith_buf, max); \
|
||||
if (result == 0) \
|
||||
result = YY_NULL; \
|
||||
else { \
|
||||
memcpy(buf, arith_buf, result); \
|
||||
arith_buf += result; \
|
||||
} \
|
||||
} while (0);
|
||||
#define YY_NO_UNPUT
|
||||
#define YY_NO_INPUT
|
||||
%}
|
||||
|
||||
%%
|
||||
[ \t\n] { ; }
|
||||
|
||||
0x[a-fA-F0-9]+ {
|
||||
yylval.l_value = strtoarith_t(yytext, NULL, 16);
|
||||
return ARITH_NUM;
|
||||
}
|
||||
|
||||
0[0-7]* {
|
||||
yylval.l_value = strtoarith_t(yytext, NULL, 8);
|
||||
return ARITH_NUM;
|
||||
}
|
||||
|
||||
[1-9][0-9]* {
|
||||
yylval.l_value = strtoarith_t(yytext, NULL, 10);
|
||||
return ARITH_NUM;
|
||||
}
|
||||
|
||||
[A-Za-z][A-Za-z0-9_]* {
|
||||
/*
|
||||
* If variable doesn't exist, we should initialize
|
||||
* it to zero.
|
||||
*/
|
||||
char *temp;
|
||||
if (lookupvar(yytext) == NULL)
|
||||
setvarsafe(yytext, "0", 0);
|
||||
temp = stalloc(strlen(yytext) + 1);
|
||||
yylval.s_value = strcpy(temp, yytext);
|
||||
|
||||
return ARITH_VAR;
|
||||
}
|
||||
|
||||
"(" { return ARITH_LPAREN; }
|
||||
")" { return ARITH_RPAREN; }
|
||||
"||" { return ARITH_OR; }
|
||||
"&&" { return ARITH_AND; }
|
||||
"|" { return ARITH_BOR; }
|
||||
"^" { return ARITH_BXOR; }
|
||||
"&" { return ARITH_BAND; }
|
||||
"==" { return ARITH_EQ; }
|
||||
"!=" { return ARITH_NE; }
|
||||
">" { return ARITH_GT; }
|
||||
">=" { return ARITH_GE; }
|
||||
"<" { return ARITH_LT; }
|
||||
"<=" { return ARITH_LE; }
|
||||
"<<" { return ARITH_LSHIFT; }
|
||||
">>" { return ARITH_RSHIFT; }
|
||||
"*" { return ARITH_MUL; }
|
||||
"/" { return ARITH_DIV; }
|
||||
"%" { return ARITH_REM; }
|
||||
"+" { return ARITH_ADD; }
|
||||
"-" { return ARITH_SUB; }
|
||||
"~" { return ARITH_BNOT; }
|
||||
"!" { return ARITH_NOT; }
|
||||
"=" { return ARITH_ASSIGN; }
|
||||
"+=" { return ARITH_ADDASSIGN; }
|
||||
"-=" { return ARITH_SUBASSIGN; }
|
||||
"*=" { return ARITH_MULASSIGN; }
|
||||
"/=" { return ARITH_DIVASSIGN; }
|
||||
"%=" { return ARITH_REMASSIGN; }
|
||||
">>=" { return ARITH_RSHASSIGN; }
|
||||
"<<=" { return ARITH_LSHASSIGN; }
|
||||
"&=" { return ARITH_BANDASSIGN; }
|
||||
"^=" { return ARITH_BXORASSIGN; }
|
||||
"|=" { return ARITH_BORASSIGN; }
|
||||
. {
|
||||
error("arith: syntax error: \"%s\"\n", arith_startbuf);
|
||||
}
|
||||
%%
|
||||
|
||||
void
|
||||
arith_lex_reset(void)
|
||||
{
|
||||
YY_NEW_FILE;
|
||||
}
|
376
bin/sh/arith_yacc.c
Normal file
376
bin/sh/arith_yacc.c
Normal file
@ -0,0 +1,376 @@
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 2007
|
||||
* Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/limits.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "arith.h"
|
||||
#include "arith_yacc.h"
|
||||
#include "expand.h"
|
||||
#include "shell.h"
|
||||
#include "error.h"
|
||||
#include "memalloc.h"
|
||||
#include "output.h"
|
||||
#include "options.h"
|
||||
#include "var.h"
|
||||
|
||||
#if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ
|
||||
#error Arithmetic tokens are out of order.
|
||||
#endif
|
||||
|
||||
static const char *arith_startbuf;
|
||||
|
||||
const char *arith_buf;
|
||||
union yystype yylval;
|
||||
|
||||
static int last_token;
|
||||
|
||||
#define ARITH_PRECEDENCE(op, prec) [op - ARITH_BINOP_MIN] = prec
|
||||
|
||||
static const char prec[ARITH_BINOP_MAX - ARITH_BINOP_MIN] = {
|
||||
ARITH_PRECEDENCE(ARITH_MUL, 0),
|
||||
ARITH_PRECEDENCE(ARITH_DIV, 0),
|
||||
ARITH_PRECEDENCE(ARITH_REM, 0),
|
||||
ARITH_PRECEDENCE(ARITH_ADD, 1),
|
||||
ARITH_PRECEDENCE(ARITH_SUB, 1),
|
||||
ARITH_PRECEDENCE(ARITH_LSHIFT, 2),
|
||||
ARITH_PRECEDENCE(ARITH_RSHIFT, 2),
|
||||
ARITH_PRECEDENCE(ARITH_LT, 3),
|
||||
ARITH_PRECEDENCE(ARITH_LE, 3),
|
||||
ARITH_PRECEDENCE(ARITH_GT, 3),
|
||||
ARITH_PRECEDENCE(ARITH_GE, 3),
|
||||
ARITH_PRECEDENCE(ARITH_EQ, 4),
|
||||
ARITH_PRECEDENCE(ARITH_NE, 4),
|
||||
ARITH_PRECEDENCE(ARITH_BAND, 5),
|
||||
ARITH_PRECEDENCE(ARITH_BXOR, 6),
|
||||
ARITH_PRECEDENCE(ARITH_BOR, 7),
|
||||
};
|
||||
|
||||
#define ARITH_MAX_PREC 8
|
||||
|
||||
static __dead2 void yyerror(const char *s)
|
||||
{
|
||||
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static arith_t arith_lookupvarint(char *varname)
|
||||
{
|
||||
const char *str;
|
||||
char *p;
|
||||
arith_t result;
|
||||
|
||||
str = lookupvar(varname);
|
||||
if (str == NULL || *str == '\0')
|
||||
str = "0";
|
||||
errno = 0;
|
||||
result = strtoarith_t(str, &p, 0);
|
||||
if (errno != 0 || *p != '\0')
|
||||
yyerror("variable conversion error");
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int arith_prec(int op)
|
||||
{
|
||||
return prec[op - ARITH_BINOP_MIN];
|
||||
}
|
||||
|
||||
static inline int higher_prec(int op1, int op2)
|
||||
{
|
||||
return arith_prec(op1) < arith_prec(op2);
|
||||
}
|
||||
|
||||
static arith_t do_binop(int op, arith_t a, arith_t b)
|
||||
{
|
||||
|
||||
switch (op) {
|
||||
default:
|
||||
case ARITH_REM:
|
||||
case ARITH_DIV:
|
||||
if (!b)
|
||||
yyerror("division by zero");
|
||||
return op == ARITH_REM ? a % b : a / b;
|
||||
case ARITH_MUL:
|
||||
return a * b;
|
||||
case ARITH_ADD:
|
||||
return a + b;
|
||||
case ARITH_SUB:
|
||||
return a - b;
|
||||
case ARITH_LSHIFT:
|
||||
return a << b;
|
||||
case ARITH_RSHIFT:
|
||||
return a >> b;
|
||||
case ARITH_LT:
|
||||
return a < b;
|
||||
case ARITH_LE:
|
||||
return a <= b;
|
||||
case ARITH_GT:
|
||||
return a > b;
|
||||
case ARITH_GE:
|
||||
return a >= b;
|
||||
case ARITH_EQ:
|
||||
return a == b;
|
||||
case ARITH_NE:
|
||||
return a != b;
|
||||
case ARITH_BAND:
|
||||
return a & b;
|
||||
case ARITH_BXOR:
|
||||
return a ^ b;
|
||||
case ARITH_BOR:
|
||||
return a | b;
|
||||
}
|
||||
}
|
||||
|
||||
static arith_t assignment(int var, int noeval);
|
||||
|
||||
static arith_t primary(int token, union yystype *val, int op, int noeval)
|
||||
{
|
||||
arith_t result;
|
||||
|
||||
again:
|
||||
switch (token) {
|
||||
case ARITH_LPAREN:
|
||||
result = assignment(op, noeval);
|
||||
if (last_token != ARITH_RPAREN)
|
||||
yyerror("expecting ')'");
|
||||
last_token = yylex();
|
||||
return result;
|
||||
case ARITH_NUM:
|
||||
last_token = op;
|
||||
return val->val;
|
||||
case ARITH_VAR:
|
||||
last_token = op;
|
||||
return noeval ? val->val : arith_lookupvarint(val->name);
|
||||
case ARITH_ADD:
|
||||
token = op;
|
||||
*val = yylval;
|
||||
op = yylex();
|
||||
goto again;
|
||||
case ARITH_SUB:
|
||||
*val = yylval;
|
||||
return -primary(op, val, yylex(), noeval);
|
||||
case ARITH_NOT:
|
||||
*val = yylval;
|
||||
return !primary(op, val, yylex(), noeval);
|
||||
case ARITH_BNOT:
|
||||
*val = yylval;
|
||||
return ~primary(op, val, yylex(), noeval);
|
||||
default:
|
||||
yyerror("expecting primary");
|
||||
}
|
||||
}
|
||||
|
||||
static arith_t binop2(arith_t a, int op, int prec, int noeval)
|
||||
{
|
||||
for (;;) {
|
||||
union yystype val;
|
||||
arith_t b;
|
||||
int op2;
|
||||
int token;
|
||||
|
||||
token = yylex();
|
||||
val = yylval;
|
||||
|
||||
b = primary(token, &val, yylex(), noeval);
|
||||
|
||||
op2 = last_token;
|
||||
if (op2 >= ARITH_BINOP_MIN && op2 < ARITH_BINOP_MAX &&
|
||||
higher_prec(op2, op)) {
|
||||
b = binop2(b, op2, arith_prec(op), noeval);
|
||||
op2 = last_token;
|
||||
}
|
||||
|
||||
a = noeval ? b : do_binop(op, a, b);
|
||||
|
||||
if (op2 < ARITH_BINOP_MIN || op2 >= ARITH_BINOP_MAX ||
|
||||
arith_prec(op2) >= prec)
|
||||
return a;
|
||||
|
||||
op = op2;
|
||||
}
|
||||
}
|
||||
|
||||
static arith_t binop(int token, union yystype *val, int op, int noeval)
|
||||
{
|
||||
arith_t a = primary(token, val, op, noeval);
|
||||
|
||||
op = last_token;
|
||||
if (op < ARITH_BINOP_MIN || op >= ARITH_BINOP_MAX)
|
||||
return a;
|
||||
|
||||
return binop2(a, op, ARITH_MAX_PREC, noeval);
|
||||
}
|
||||
|
||||
static arith_t and(int token, union yystype *val, int op, int noeval)
|
||||
{
|
||||
arith_t a = binop(token, val, op, noeval);
|
||||
arith_t b;
|
||||
|
||||
op = last_token;
|
||||
if (op != ARITH_AND)
|
||||
return a;
|
||||
|
||||
token = yylex();
|
||||
*val = yylval;
|
||||
|
||||
b = and(token, val, yylex(), noeval | !a);
|
||||
|
||||
return a && b;
|
||||
}
|
||||
|
||||
static arith_t or(int token, union yystype *val, int op, int noeval)
|
||||
{
|
||||
arith_t a = and(token, val, op, noeval);
|
||||
arith_t b;
|
||||
|
||||
op = last_token;
|
||||
if (op != ARITH_OR)
|
||||
return a;
|
||||
|
||||
token = yylex();
|
||||
*val = yylval;
|
||||
|
||||
b = or(token, val, yylex(), noeval | !!a);
|
||||
|
||||
return a || b;
|
||||
}
|
||||
|
||||
static arith_t cond(int token, union yystype *val, int op, int noeval)
|
||||
{
|
||||
arith_t a = or(token, val, op, noeval);
|
||||
arith_t b;
|
||||
arith_t c;
|
||||
|
||||
if (last_token != ARITH_QMARK)
|
||||
return a;
|
||||
|
||||
b = assignment(yylex(), noeval | !a);
|
||||
|
||||
if (last_token != ARITH_COLON)
|
||||
yyerror("expecting ':'");
|
||||
|
||||
token = yylex();
|
||||
*val = yylval;
|
||||
|
||||
c = cond(token, val, yylex(), noeval | !!a);
|
||||
|
||||
return a ? b : c;
|
||||
}
|
||||
|
||||
static arith_t assignment(int var, int noeval)
|
||||
{
|
||||
union yystype val = yylval;
|
||||
int op = yylex();
|
||||
arith_t result;
|
||||
char sresult[DIGITS(result) + 1];
|
||||
|
||||
if (var != ARITH_VAR)
|
||||
return cond(var, &val, op, noeval);
|
||||
|
||||
if (op != ARITH_ASS && (op < ARITH_ASS_MIN || op >= ARITH_ASS_MAX))
|
||||
return cond(var, &val, op, noeval);
|
||||
|
||||
result = assignment(yylex(), noeval);
|
||||
if (noeval)
|
||||
return result;
|
||||
|
||||
if (op != ARITH_ASS)
|
||||
result = do_binop(op - 11, arith_lookupvarint(val.name), result);
|
||||
snprintf(sresult, sizeof(sresult), ARITH_FORMAT_STR, result);
|
||||
setvar(val.name, sresult, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
arith_t arith(const char *s)
|
||||
{
|
||||
struct stackmark smark;
|
||||
arith_t result;
|
||||
|
||||
setstackmark(&smark);
|
||||
|
||||
arith_buf = arith_startbuf = s;
|
||||
|
||||
result = assignment(yylex(), 0);
|
||||
|
||||
if (last_token)
|
||||
yyerror("expecting EOF");
|
||||
|
||||
popstackmark(&smark);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* The exp(1) builtin.
|
||||
*/
|
||||
int
|
||||
expcmd(int argc, char **argv)
|
||||
{
|
||||
const char *p;
|
||||
char *concat;
|
||||
char **ap;
|
||||
arith_t i;
|
||||
|
||||
if (argc > 1) {
|
||||
p = argv[1];
|
||||
if (argc > 2) {
|
||||
/*
|
||||
* Concatenate arguments.
|
||||
*/
|
||||
STARTSTACKSTR(concat);
|
||||
ap = argv + 2;
|
||||
for (;;) {
|
||||
while (*p)
|
||||
STPUTC(*p++, concat);
|
||||
if ((p = *ap++) == NULL)
|
||||
break;
|
||||
STPUTC(' ', concat);
|
||||
}
|
||||
STPUTC('\0', concat);
|
||||
p = grabstackstr(concat);
|
||||
}
|
||||
} else
|
||||
p = "";
|
||||
|
||||
i = arith(p);
|
||||
|
||||
out1fmt(ARITH_FORMAT_STR "\n", i);
|
||||
return !i;
|
||||
}
|
||||
|
91
bin/sh/arith_yacc.h
Normal file
91
bin/sh/arith_yacc.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 2007
|
||||
* Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define ARITH_ASS 1
|
||||
|
||||
#define ARITH_OR 2
|
||||
#define ARITH_AND 3
|
||||
#define ARITH_BAD 4
|
||||
#define ARITH_NUM 5
|
||||
#define ARITH_VAR 6
|
||||
#define ARITH_NOT 7
|
||||
|
||||
#define ARITH_BINOP_MIN 8
|
||||
#define ARITH_LE 8
|
||||
#define ARITH_GE 9
|
||||
#define ARITH_LT 10
|
||||
#define ARITH_GT 11
|
||||
#define ARITH_EQ 12
|
||||
#define ARITH_REM 13
|
||||
#define ARITH_BAND 14
|
||||
#define ARITH_LSHIFT 15
|
||||
#define ARITH_RSHIFT 16
|
||||
#define ARITH_MUL 17
|
||||
#define ARITH_ADD 18
|
||||
#define ARITH_BOR 19
|
||||
#define ARITH_SUB 20
|
||||
#define ARITH_BXOR 21
|
||||
#define ARITH_DIV 22
|
||||
#define ARITH_NE 23
|
||||
#define ARITH_BINOP_MAX 24
|
||||
|
||||
#define ARITH_ASS_MIN 24
|
||||
#define ARITH_REMASS 24
|
||||
#define ARITH_BANDASS 25
|
||||
#define ARITH_LSHIFTASS 26
|
||||
#define ARITH_RSHIFTASS 27
|
||||
#define ARITH_MULASS 28
|
||||
#define ARITH_ADDASS 29
|
||||
#define ARITH_BORASS 30
|
||||
#define ARITH_SUBASS 31
|
||||
#define ARITH_BXORASS 32
|
||||
#define ARITH_DIVASS 33
|
||||
#define ARITH_ASS_MAX 34
|
||||
|
||||
#define ARITH_LPAREN 34
|
||||
#define ARITH_RPAREN 35
|
||||
#define ARITH_BNOT 36
|
||||
#define ARITH_QMARK 37
|
||||
#define ARITH_COLON 38
|
||||
|
||||
union yystype {
|
||||
arith_t val;
|
||||
char *name;
|
||||
};
|
||||
|
||||
extern union yystype yylval;
|
||||
|
||||
int yylex(void);
|
244
bin/sh/arith_yylex.c
Normal file
244
bin/sh/arith_yylex.c
Normal file
@ -0,0 +1,244 @@
|
||||
/*-
|
||||
* Copyright (c) 2002
|
||||
* Herbert Xu.
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "shell.h"
|
||||
#include "arith_yacc.h"
|
||||
#include "expand.h"
|
||||
#include "error.h"
|
||||
#include "memalloc.h"
|
||||
#include "parser.h"
|
||||
#include "syntax.h"
|
||||
|
||||
#if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ
|
||||
#error Arithmetic tokens are out of order.
|
||||
#endif
|
||||
|
||||
extern const char *arith_buf;
|
||||
|
||||
int
|
||||
yylex()
|
||||
{
|
||||
int value;
|
||||
const char *buf = arith_buf;
|
||||
const char *p;
|
||||
|
||||
for (;;) {
|
||||
value = *buf;
|
||||
switch (value) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
buf++;
|
||||
continue;
|
||||
default:
|
||||
return ARITH_BAD;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
yylval.val = strtoarith_t(buf, (char **)&arith_buf, 0);
|
||||
return ARITH_NUM;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'G':
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'J':
|
||||
case 'K':
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'N':
|
||||
case 'O':
|
||||
case 'P':
|
||||
case 'Q':
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'T':
|
||||
case 'U':
|
||||
case 'V':
|
||||
case 'W':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
case 'Z':
|
||||
case '_':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z':
|
||||
p = buf;
|
||||
while (buf++, is_in_name(*buf))
|
||||
;
|
||||
yylval.name = stalloc(buf - p + 1);
|
||||
memcpy(yylval.name, p, buf - p);
|
||||
yylval.name[buf - p] = '\0';
|
||||
value = ARITH_VAR;
|
||||
goto out;
|
||||
case '=':
|
||||
value += ARITH_ASS - '=';
|
||||
checkeq:
|
||||
buf++;
|
||||
checkeqcur:
|
||||
if (*buf != '=')
|
||||
goto out;
|
||||
value += 11;
|
||||
break;
|
||||
case '>':
|
||||
switch (*++buf) {
|
||||
case '=':
|
||||
value += ARITH_GE - '>';
|
||||
break;
|
||||
case '>':
|
||||
value += ARITH_RSHIFT - '>';
|
||||
goto checkeq;
|
||||
default:
|
||||
value += ARITH_GT - '>';
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
switch (*++buf) {
|
||||
case '=':
|
||||
value += ARITH_LE - '<';
|
||||
break;
|
||||
case '<':
|
||||
value += ARITH_LSHIFT - '<';
|
||||
goto checkeq;
|
||||
default:
|
||||
value += ARITH_LT - '<';
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case '|':
|
||||
if (*++buf != '|') {
|
||||
value += ARITH_BOR - '|';
|
||||
goto checkeqcur;
|
||||
}
|
||||
value += ARITH_OR - '|';
|
||||
break;
|
||||
case '&':
|
||||
if (*++buf != '&') {
|
||||
value += ARITH_BAND - '&';
|
||||
goto checkeqcur;
|
||||
}
|
||||
value += ARITH_AND - '&';
|
||||
break;
|
||||
case '!':
|
||||
if (*++buf != '=') {
|
||||
value += ARITH_NOT - '!';
|
||||
goto out;
|
||||
}
|
||||
value += ARITH_NE - '!';
|
||||
break;
|
||||
case 0:
|
||||
goto out;
|
||||
case '(':
|
||||
value += ARITH_LPAREN - '(';
|
||||
break;
|
||||
case ')':
|
||||
value += ARITH_RPAREN - ')';
|
||||
break;
|
||||
case '*':
|
||||
value += ARITH_MUL - '*';
|
||||
goto checkeq;
|
||||
case '/':
|
||||
value += ARITH_DIV - '/';
|
||||
goto checkeq;
|
||||
case '%':
|
||||
value += ARITH_REM - '%';
|
||||
goto checkeq;
|
||||
case '+':
|
||||
value += ARITH_ADD - '+';
|
||||
goto checkeq;
|
||||
case '-':
|
||||
value += ARITH_SUB - '-';
|
||||
goto checkeq;
|
||||
case '~':
|
||||
value += ARITH_BNOT - '~';
|
||||
break;
|
||||
case '^':
|
||||
value += ARITH_BXOR - '^';
|
||||
goto checkeq;
|
||||
case '?':
|
||||
value += ARITH_QMARK - '?';
|
||||
break;
|
||||
case ':':
|
||||
value += ARITH_COLON - ':';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buf++;
|
||||
out:
|
||||
arith_buf = buf;
|
||||
return value;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user