diff --git a/Build.sh b/Build.sh index 4dba79c..ce0dc0d 100644 --- a/Build.sh +++ b/Build.sh @@ -1,5 +1,5 @@ #!/bin/sh -srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.700 2016/07/25 21:05:18 tg Exp $' +srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.701 2016/07/27 00:55:26 tg Exp $' #- # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013, 2014, 2015, 2016 @@ -2498,7 +2498,7 @@ echo tcfn=$mkshexe >>Rebuild.sh echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh if test $cm = makefile; then - extras='emacsfn.h rlimits.opt sh.h sh_flags.opt var_spec.h' + extras='emacsfn.h exprtok.h rlimits.opt sh.h sh_flags.opt var_spec.h' test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc" gens= genq= for file in $optfiles; do diff --git a/expr.c b/expr.c index 1ea51b5..e40108f 100644 --- a/expr.c +++ b/expr.c @@ -23,44 +23,10 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.87 2016/07/25 20:41:23 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.88 2016/07/27 00:55:27 tg Exp $"); -/* the order of these enums is constrained by the order of opinfo[] */ -enum token { - /* some (long) unary operators */ - O_PLUSPLUS = 0, O_MINUSMINUS, - /* binary operators */ - O_EQ, O_NE, - /* assignments are assumed to be in range O_ASN .. O_BORASN */ - O_ASN, O_TIMESASN, O_DIVASN, O_MODASN, O_PLUSASN, O_MINUSASN, -#ifndef MKSH_LEGACY_MODE - O_ROLASN, O_RORASN, -#endif - O_LSHIFTASN, O_RSHIFTASN, O_BANDASN, O_BXORASN, O_BORASN, - /* binary non-assignment operators */ -#ifndef MKSH_LEGACY_MODE - O_ROL, O_ROR, -#endif - O_LSHIFT, O_RSHIFT, - O_LE, O_GE, O_LT, O_GT, - O_LAND, - O_LOR, - O_TIMES, O_DIV, O_MOD, - O_PLUS, O_MINUS, - O_BAND, - O_BXOR, - O_BOR, - O_TERN, - O_COMMA, - /* things after this aren't used as binary operators */ - /* unary that are not also binaries */ - O_BNOT, O_LNOT, - /* misc */ - OPEN_PAREN, CLOSE_PAREN, CTERN, - /* things that don't appear in the opinfo[] table */ - VAR, LIT, END, BAD -}; -#define IS_ASSIGNOP(op) ((int)(op) >= (int)O_ASN && (int)(op) <= (int)O_BORASN) +#define EXPRTOK_DEFNS +#include "exprtok.h" /* precisions; used to be enum prec but we do arithmetics on it */ #define P_PRIMARY 0 /* VAR, LIT, (), ! ~ ++ -- */ @@ -80,67 +46,24 @@ enum token { #define P_COMMA 13 /* , */ #define MAX_PREC P_COMMA -struct opinfo { - char name[4]; - /* name length */ - uint8_t len; - /* precedence: lower is higher */ - uint8_t prec; +enum token { +#define EXPRTOK_ENUM +#include "exprtok.h" }; -/* - * Tokens in this table must be ordered so the longest are first - * (eg, += before +). If you change something, change the order - * of enum token too. - */ -static const struct opinfo opinfo[] = { - { "++", 2, P_PRIMARY }, /* before + */ - { "--", 2, P_PRIMARY }, /* before - */ - { "==", 2, P_EQUALITY }, /* before = */ - { "!=", 2, P_EQUALITY }, /* before ! */ - { "=", 1, P_ASSIGN }, /* keep assigns in a block */ - { "*=", 2, P_ASSIGN }, - { "/=", 2, P_ASSIGN }, - { "%=", 2, P_ASSIGN }, - { "+=", 2, P_ASSIGN }, - { "-=", 2, P_ASSIGN }, -#ifndef MKSH_LEGACY_MODE - { "^<=", 3, P_ASSIGN }, /* before ^< */ - { "^>=", 3, P_ASSIGN }, /* before ^> */ -#endif - { "<<=", 3, P_ASSIGN }, - { ">>=", 3, P_ASSIGN }, - { "&=", 2, P_ASSIGN }, - { "^=", 2, P_ASSIGN }, - { "|=", 2, P_ASSIGN }, -#ifndef MKSH_LEGACY_MODE - { "^<", 2, P_SHIFT }, /* before ^ */ - { "^>", 2, P_SHIFT }, /* before ^ */ -#endif - { "<<", 2, P_SHIFT }, - { ">>", 2, P_SHIFT }, - { "<=", 2, P_RELATION }, - { ">=", 2, P_RELATION }, - { "<", 1, P_RELATION }, - { ">", 1, P_RELATION }, - { "&&", 2, P_LAND }, - { "||", 2, P_LOR }, - { "*", 1, P_MULT }, - { "/", 1, P_MULT }, - { "%", 1, P_MULT }, - { "+", 1, P_ADD }, - { "-", 1, P_ADD }, - { "&", 1, P_BAND }, - { "^", 1, P_BXOR }, - { "|", 1, P_BOR }, - { "?", 1, P_TERN }, - { ",", 1, P_COMMA }, - { "~", 1, P_PRIMARY }, - { "!", 1, P_PRIMARY }, - { "(", 1, P_PRIMARY }, - { ")", 1, P_PRIMARY }, - { ":", 1, P_PRIMARY }, - { "", 0, P_PRIMARY } +static const char opname[][4] = { +#define EXPRTOK_NAME +#include "exprtok.h" +}; + +static const uint8_t oplen[] = { +#define EXPRTOK_LEN +#include "exprtok.h" +}; + +static const uint8_t opprec[] = { +#define EXPRTOK_PREC +#include "exprtok.h" }; typedef struct expr_state { @@ -272,7 +195,7 @@ evalerr(Expr_state *es, enum error_type type, const char *str) s = tbuf; break; default: - s = opinfo[(int)es->tok].name; + s = opname[(int)es->tok]; } warningf(true, Tf_sD_s_qs, es->expression, Tunexpected, s); @@ -402,7 +325,7 @@ evalexpr(Expr_state *es, unsigned int prec) vl = evalexpr(es, prec - 1); while ((int)(op = es->tok) >= (int)O_EQ && (int)op <= (int)O_COMMA && - opinfo[(int)op].prec == prec) { + opprec[(int)op] == prec) { exprtoken(es); vasn = vl; if (op != O_ASN) @@ -698,11 +621,11 @@ exprtoken(Expr_state *es) } else { int i, n0; - for (i = 0; (n0 = opinfo[i].name[0]); i++) - if (c == n0 && strncmp(cp, opinfo[i].name, - (size_t)opinfo[i].len) == 0) { + for (i = 0; (n0 = opname[i][0]); i++) + if (c == n0 && strncmp(cp, opname[i], + (size_t)oplen[i]) == 0) { es->tok = (enum token)i; - cp += opinfo[i].len; + cp += oplen[i]; break; } if (!n0) @@ -716,9 +639,9 @@ assign_check(Expr_state *es, enum token op, struct tbl *vasn) { if (es->tok == END || !vasn || (vasn->name[0] == '\0' && !(vasn->flag & EXPRLVALUE))) - evalerr(es, ET_LVALUE, opinfo[(int)op].name); + evalerr(es, ET_LVALUE, opname[(int)op]); else if (vasn->flag & RDONLY) - evalerr(es, ET_RDONLY, opinfo[(int)op].name); + evalerr(es, ET_RDONLY, opname[(int)op]); } struct tbl * diff --git a/exprtok.h b/exprtok.h new file mode 100644 index 0000000..8a98926 --- /dev/null +++ b/exprtok.h @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2016 + * mirabilos + * + * Provided that these terms and disclaimer and all copyright notices + * are retained or reproduced in an accompanying document, permission + * is granted to deal in this work without restriction, including un- + * limited rights to use, publicly perform, distribute, sell, modify, + * merge, give away, or sublicence. + * + * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to + * the utmost extent permitted by applicable law, neither express nor + * implied; without malicious intent or gross negligence. In no event + * may a licensor, author or contributor be held liable for indirect, + * direct, other damage, loss, or other issues arising in any way out + * of dealing in the work, even if advised of the possibility of such + * damage or existence of a defect, except proven that it results out + * of said person's immediate fault when using the work as intended. + */ + +#if defined(EXPRTOK_DEFNS) +__RCSID("$MirOS: src/bin/mksh/exprtok.h,v 1.1 2016/07/27 00:55:27 tg Exp $"); +/* see range comment below */ +#define IS_ASSIGNOP(op) ((int)(op) >= (int)O_ASN && (int)(op) <= (int)O_BORASN) +#define FN(name, len, prec, enum) /* nothing */ +#define F1(enum) /* nothing */ +#elif defined(EXPRTOK_ENUM) +#define F0(name, len, prec, enum) enum = 0, +#define FN(name, len, prec, enum) enum, +#define F1(enum) enum, +#define F2(enum) enum, +#define F9(enum) enum +#elif defined(EXPRTOK_NAME) +#define FN(name, len, prec, enum) name, +#define F1(enum) "" +#elif defined(EXPRTOK_LEN) +#define FN(name, len, prec, enum) len, +#define F1(enum) 0 +#elif defined(EXPRTOK_PREC) +#define FN(name, len, prec, enum) prec, +#define F1(enum) P_PRIMARY +#endif + +#ifndef F0 +#define F0 FN +#endif + +#ifndef F2 +#define F2(enum) /* nothing */ +#define F9(enum) /* nothing */ +#endif + +/* tokens must be ordered so the longest are first (e.g. += before +) */ + +/* some (long) unary operators */ +FN("++", 2, P_PRIMARY, O_PLUSPLUS = 0) /* before + */ +FN("--", 2, P_PRIMARY, O_MINUSMINUS) /* before - */ +/* binary operators */ +FN("==", 2, P_EQUALITY, O_EQ) /* before = */ +FN("!=", 2, P_EQUALITY, O_NE) /* before ! */ +/* assignments are assumed to be in range O_ASN .. O_BORASN */ +FN("=", 1, P_ASSIGN, O_ASN) +FN("*=", 2, P_ASSIGN, O_TIMESASN) +FN("/-", 2, P_ASSIGN, O_DIVASN) +FN("%=", 2, P_ASSIGN, O_MODASN) +FN("+=", 2, P_ASSIGN, O_PLUSASN) +FN("-=", 2, P_ASSIGN, O_MINUSASN) +#ifndef MKSH_LEGACY_MODE +FN("^<=", 3, P_ASSIGN, O_ROLASN) /* before ^< */ +FN("^>=", 3, P_ASSIGN, O_RORASN) /* before ^> */ +#endif +FN("<<=", 3, P_ASSIGN, O_LSHIFTASN) +FN(">>=", 3, P_ASSIGN, O_RSHIFTASN) +FN("&=", 2, P_ASSIGN, O_BANDASN) +FN("^=", 2, P_ASSIGN, O_BXORASN) +FN("|=", 2, P_ASSIGN, O_BORASN) +/* binary non-assignment operators */ +#ifndef MKSH_LEGACY_MODE +FN("^<", 2, P_SHIFT, O_ROL) /* before ^ */ +FN("^>", 2, P_SHIFT, O_ROR) /* before ^ */ +#endif +FN("<<", 2, P_SHIFT, O_LSHIFT) +FN(">>", 2, P_SHIFT, O_RSHIFT) +FN("<=", 2, P_RELATION, O_LE) +FN(">=", 2, P_RELATION, O_GE) +FN("<", 1, P_RELATION, O_LT) +FN(">", 1, P_RELATION, O_GT) +FN("&&", 2, P_LAND, O_LAND) +FN("||", 2, P_LOR, O_LOR) +FN("*", 1, P_MULT, O_TIMES) +FN("/", 1, P_MULT, O_DIV) +FN("%", 1, P_MULT, O_MOD) +FN("+", 1, P_ADD, O_PLUS) +FN("-", 1, P_ADD, O_MINUS) +FN("&", 1, P_BAND, O_BAND) +FN("^", 1, P_BXOR, O_BXOR) +FN("|", 1, P_BOR, O_BOR) +FN("?", 1, P_TERN, O_TERN) +FN(",", 1, P_COMMA, O_COMMA) +/* things after this aren't used as binary operators */ +/* unary that are not also binaries */ +FN("~", 1, P_PRIMARY, O_BNOT) +FN("!", 1, P_PRIMARY, O_LNOT) +/* misc */ +FN("(", 1, P_PRIMARY, OPEN_PAREN) +FN(")", 1, P_PRIMARY, CLOSE_PAREN) +FN(":", 1, P_PRIMARY, CTERN) +/* things that don't appear in the opinfo[] table */ +F1(VAR) /*XXX should be F2 */ +F2(LIT) +F2(END) +F9(BAD) + +#undef FN +#undef F0 +#undef F1 +#undef F2 +#undef F9 +#undef EXPRTOK_DEFNS +#undef EXPRTOK_ENUM +#undef EXPRTOK_NAME +#undef EXPRTOK_LEN +#undef EXPRTOK_PREC