150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes/* $OpenBSD: expr.c,v 1.24 2014/12/08 14:26:31 otto Exp $ */ 25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*- 4c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 5737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes * 2011, 2012, 2013, 2014 65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Thorsten Glaser <tg@mirbsd.org> 75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices 95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission 105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un- 115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify, 125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence. 135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor 165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event 175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect, 185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out 195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such 205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out 215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended. 225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h" 255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2650012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76.2.1 2015/01/25 15:44:05 tg Exp $"); 27c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 28811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser/* the order of these enums is constrained by the order of opinfo[] */ 295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruenum token { 305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* some (long) unary operators */ 315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_PLUSPLUS = 0, O_MINUSMINUS, 325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* binary operators */ 335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_EQ, O_NE, 345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* assignments are assumed to be in range O_ASN .. O_BORASN */ 355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_ASN, O_TIMESASN, O_DIVASN, O_MODASN, O_PLUSASN, O_MINUSASN, 36811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_LEGACY_MODE 37811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser O_ROLASN, O_RORASN, 38811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif 395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_LSHIFTASN, O_RSHIFTASN, O_BANDASN, O_BXORASN, O_BORASN, 40811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* binary non-assignment operators */ 41811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_LEGACY_MODE 42811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser O_ROL, O_ROR, 43811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif 445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_LSHIFT, O_RSHIFT, 455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_LE, O_GE, O_LT, O_GT, 465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_LAND, 475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_LOR, 485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_TIMES, O_DIV, O_MOD, 495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_PLUS, O_MINUS, 505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_BAND, 515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_BXOR, 525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_BOR, 535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_TERN, 545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_COMMA, 555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* things after this aren't used as binary operators */ 565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* unary that are not also binaries */ 575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru O_BNOT, O_LNOT, 585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* misc */ 595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru OPEN_PAREN, CLOSE_PAREN, CTERN, 605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* things that don't appear in the opinfo[] table */ 615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru VAR, LIT, END, BAD 625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define IS_ASSIGNOP(op) ((int)(op) >= (int)O_ASN && (int)(op) <= (int)O_BORASN) 645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* precisions; used to be enum prec but we do arithmetics on it */ 66811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#define P_PRIMARY 0 /* VAR, LIT, (), ! ~ ++ -- */ 675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_MULT 1 /* * / % */ 685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_ADD 2 /* + - */ 69811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#define P_SHIFT 3 /* <<< >>> << >> */ 705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_RELATION 4 /* < <= > >= */ 715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_EQUALITY 5 /* == != */ 725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_BAND 6 /* & */ 735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_BXOR 7 /* ^ */ 745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_BOR 8 /* | */ 755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_LAND 9 /* && */ 765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_LOR 10 /* || */ 775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_TERN 11 /* ?: */ 78811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* = += -= *= /= %= <<<= >>>= <<= >>= &= ^= |= */ 79811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#define P_ASSIGN 12 805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define P_COMMA 13 /* , */ 815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define MAX_PREC P_COMMA 825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct opinfo { 84811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char name[5]; 85811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* name length */ 86811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser uint8_t len; 87811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* precedence: lower is higher */ 88811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser uint8_t prec; 895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 91811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser/* 92811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * Tokens in this table must be ordered so the longest are first 935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (eg, += before +). If you change something, change the order 945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of enum token too. 955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const struct opinfo opinfo[] = { 97811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "++", 2, P_PRIMARY }, /* before + */ 98811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "--", 2, P_PRIMARY }, /* before - */ 99811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "==", 2, P_EQUALITY }, /* before = */ 100811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "!=", 2, P_EQUALITY }, /* before ! */ 101811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "=", 1, P_ASSIGN }, /* keep assigns in a block */ 102811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "*=", 2, P_ASSIGN }, 103811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "/=", 2, P_ASSIGN }, 104811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "%=", 2, P_ASSIGN }, 105811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "+=", 2, P_ASSIGN }, 106811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "-=", 2, P_ASSIGN }, 107811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_LEGACY_MODE 108811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "<<<=", 4, P_ASSIGN }, /* before <<< */ 109811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { ">>>=", 4, P_ASSIGN }, /* before >>> */ 110811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif 111811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "<<=", 3, P_ASSIGN }, 112811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { ">>=", 3, P_ASSIGN }, 113811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "&=", 2, P_ASSIGN }, 114811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "^=", 2, P_ASSIGN }, 115811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "|=", 2, P_ASSIGN }, 116811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_LEGACY_MODE 117811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "<<<", 3, P_SHIFT }, /* before << */ 118811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { ">>>", 3, P_SHIFT }, /* before >> */ 119811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif 120811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "<<", 2, P_SHIFT }, 121811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { ">>", 2, P_SHIFT }, 122811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "<=", 2, P_RELATION }, 123811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { ">=", 2, P_RELATION }, 124811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "<", 1, P_RELATION }, 125811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { ">", 1, P_RELATION }, 126811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "&&", 2, P_LAND }, 127811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "||", 2, P_LOR }, 128811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "*", 1, P_MULT }, 129811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "/", 1, P_MULT }, 130811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "%", 1, P_MULT }, 131811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "+", 1, P_ADD }, 132811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "-", 1, P_ADD }, 133811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "&", 1, P_BAND }, 134811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "^", 1, P_BXOR }, 135811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "|", 1, P_BOR }, 136811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "?", 1, P_TERN }, 137811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { ",", 1, P_COMMA }, 138811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "~", 1, P_PRIMARY }, 139811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "!", 1, P_PRIMARY }, 140811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "(", 1, P_PRIMARY }, 141811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { ")", 1, P_PRIMARY }, 142811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { ":", 1, P_PRIMARY }, 143811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { "", 0, P_PRIMARY } 1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 146c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasertypedef struct expr_state { 147c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* expression being evaluated */ 148c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser const char *expression; 149c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* lexical position */ 150c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser const char *tokp; 151c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* value from token() */ 152c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct tbl *val; 153c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* variable that is being recursively expanded (EXPRINEVAL flag set) */ 154c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct tbl *evaling; 155c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* token from token() */ 156c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser enum token tok; 157c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* don't do assignments (for ?:, &&, ||) */ 158811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser uint8_t noassign; 159c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* evaluating an $(()) expression? */ 160c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool arith; 161c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* unsigned arithmetic calculation */ 162c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool natural; 163c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} Expr_state; 1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruenum error_type { 1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ET_UNEXPECTED, ET_BADLIT, ET_RECURSIVE, 1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ET_LVALUE, ET_RDONLY, ET_STR 1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void evalerr(Expr_state *, enum error_type, const char *) 1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru MKSH_A_NORETURN; 172811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic struct tbl *evalexpr(Expr_state *, unsigned int); 1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void exprtoken(Expr_state *); 1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct tbl *do_ppmm(Expr_state *, enum token, struct tbl *, bool); 1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void assign_check(Expr_state *, enum token, struct tbl *); 1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct tbl *intvar(Expr_state *, struct tbl *); 1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * parse and evaluate expression 1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruevaluate(const char *expr, mksh_ari_t *rval, int error_ok, bool arith) 1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl v; 1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int ret; 1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 187811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser v.flag = DEFINED | INTEGER; 1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru v.type = 0; 1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = v_evaluate(&v, expr, error_ok, arith); 1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *rval = v.val.i; 1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (ret); 1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * parse and evaluate expression, storing result in vp. 1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruv_evaluate(struct tbl *vp, const char *expr, volatile int error_ok, 1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool arith) 2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *v; 2025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Expr_state curstate; 2035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Expr_state * const es = &curstate; 2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* save state to allow recursive calls */ 207c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memset(&curstate, 0, sizeof(curstate)); 2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru curstate.expression = curstate.tokp = expr; 209c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser curstate.tok = BAD; 2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru curstate.arith = arith; 2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newenv(E_ERRH); 213c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((i = kshsetjmp(e->jbuf))) { 2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Clear EXPRINEVAL in of any variables we were playing with */ 2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (curstate.evaling) 2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru curstate.evaling->flag &= ~EXPRINEVAL; 2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i == LAEXPR) { 2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (error_ok == KSH_RETURN_ERROR) 2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 2215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorfz(); 2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(i); 2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exprtoken(es); 2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (es->tok == END) { 2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->tok = LIT; 2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->val = tempvar(); 2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru v = intvar(es, evalexpr(es, MAX_PREC)); 2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (es->tok != END) 2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru evalerr(es, ET_UNEXPECTED, NULL); 2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (es->arith && es->natural) 2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->flag |= INT_U; 2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vp->flag & INTEGER) 2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setint_v(vp, v, es->arith); 2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* can fail if readonly */ 2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setstr(vp, str_val(v), error_ok); 2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruevalerr(Expr_state *es, enum error_type type, const char *str) 2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char tbuf[2]; 2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *s; 2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->arith = false; 2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (type) { 2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ET_UNEXPECTED: 2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (es->tok) { 2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case VAR: 2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = es->val->name; 2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LIT: 2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = str_val(es->val); 2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case END: 2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = "end of expression"; 2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case BAD: 2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tbuf[0] = *es->tokp; 2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tbuf[1] = '\0'; 2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = tbuf; 2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = opinfo[(int)es->tok].name; 2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 27703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s '%s'", es->expression, 27803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "unexpected", s); 2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ET_BADLIT: 28203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s '%s'", es->expression, 28303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "bad number", str); 2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ET_RECURSIVE: 28703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s '%s'", es->expression, 28803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "expression recurses on parameter", str); 2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ET_LVALUE: 29203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s %s", 29303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra es->expression, str, "requires lvalue"); 2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ET_RDONLY: 29703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s %s", 298c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser es->expression, str, "applied to read-only variable"); 2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: /* keep gcc happy */ 3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case ET_STR: 3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru warningf(true, "%s: %s", es->expression, str); 3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LAEXPR); 3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 309811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser/* do a ++ or -- operation */ 3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct tbl * 311811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserdo_ppmm(Expr_state *es, enum token op, struct tbl *vasn, bool is_prefix) 312811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser{ 313811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser struct tbl *vl; 314811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser mksh_uari_t oval; 315811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 316811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser assign_check(es, op, vasn); 317811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 318811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vl = intvar(es, vasn); 319811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser oval = vl->val.u; 320811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (op == O_PLUSPLUS) 321811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ++vl->val.u; 322811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser else 323811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser --vl->val.u; 324811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!es->noassign) { 325811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (vasn->flag & INTEGER) 326811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser setint_v(vasn, vl, es->arith); 327811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser else 328811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser setint(vasn, vl->val.i); 329811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 330811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!is_prefix) 331811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* undo the increment/decrement */ 332811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vl->val.u = oval; 333811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 334811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (vl); 335811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser} 336811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 337811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic struct tbl * 338811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserevalexpr(Expr_state *es, unsigned int prec) 3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *vl, *vr = NULL, *vasn; 3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru enum token op; 342811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser mksh_uari_t res = 0, t1, t2, t3; 3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (prec == P_PRIMARY) { 345811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser switch ((int)(op = es->tok)) { 346811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_BNOT: 347811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_LNOT: 348811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_MINUS: 349811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_PLUS: 3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exprtoken(es); 3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vl = intvar(es, evalexpr(es, P_PRIMARY)); 352811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser switch ((int)op) { 353811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_BNOT: 354811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vl->val.u = ~vl->val.u; 355811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 356811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_LNOT: 357811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vl->val.u = !vl->val.u; 358811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 359811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_MINUS: 360811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vl->val.u = -vl->val.u; 361811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 362811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_PLUS: 363811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* nop */ 364811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 365811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 366811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 367811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 368811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case OPEN_PAREN: 3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exprtoken(es); 3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vl = evalexpr(es, MAX_PREC); 3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (es->tok != CLOSE_PAREN) 3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru evalerr(es, ET_STR, "missing )"); 3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exprtoken(es); 374811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 375811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 376811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_PLUSPLUS: 377811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_MINUSMINUS: 3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exprtoken(es); 3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vl = do_ppmm(es, op, es->val, true); 3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exprtoken(es); 381811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 382811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 383811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case VAR: 384811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case LIT: 3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vl = es->val; 3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exprtoken(es); 387811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 388811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 389811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser default: 3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru evalerr(es, ET_UNEXPECTED, NULL); 3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 393811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (es->tok == O_PLUSPLUS || es->tok == O_MINUSMINUS) { 3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vl = do_ppmm(es, es->tok, vl, false); 3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exprtoken(es); 3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 398811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (vl); 400811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* prec == P_PRIMARY */ 4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 402811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vl = evalexpr(es, prec - 1); 404811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser while ((int)(op = es->tok) >= (int)O_EQ && (int)op <= (int)O_COMMA && 405811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser opinfo[(int)op].prec == prec) { 4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exprtoken(es); 4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vasn = vl; 408c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (op != O_ASN) 409c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* vl may not have a value yet */ 4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vl = intvar(es, vl); 4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (IS_ASSIGNOP(op)) { 412c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!es->noassign) 413c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser assign_check(es, op, vasn); 4145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vr = intvar(es, evalexpr(es, P_ASSIGN)); 415811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } else if (op == O_TERN) { 416811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser bool ev = vl->val.u != 0; 417811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 418811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!ev) 419811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser es->noassign++; 420811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vl = evalexpr(es, MAX_PREC); 421811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!ev) 422811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser es->noassign--; 423811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (es->tok != CTERN) 424811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser evalerr(es, ET_STR, "missing :"); 425811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser exprtoken(es); 426811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (ev) 427811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser es->noassign++; 428811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vr = evalexpr(es, P_TERN); 429811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (ev) 430811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser es->noassign--; 431811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vl = ev ? vl : vr; 432811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser continue; 433811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } else if (op != O_LAND && op != O_LOR) 4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vr = intvar(es, evalexpr(es, prec - 1)); 435811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 436811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* common ops setup */ 437811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser switch ((int)op) { 438811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_DIV: 439811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_DIVASN: 440811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_MOD: 441811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_MODASN: 442811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (vr->val.u == 0) { 443811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!es->noassign) 444811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser evalerr(es, ET_STR, "zero divisor"); 445811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser vr->val.u = 1; 446811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 447811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* calculate the absolute values */ 448811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t1 = vl->val.i < 0 ? -vl->val.u : vl->val.u; 449811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t2 = vr->val.i < 0 ? -vr->val.u : vr->val.u; 450811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 451811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_LEGACY_MODE 452811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_LSHIFT: 453811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_LSHIFTASN: 454811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_RSHIFT: 455811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_RSHIFTASN: 456811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_ROL: 457811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_ROLASN: 458811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_ROR: 459811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_RORASN: 460811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t1 = vl->val.u; 461811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t2 = vr->val.u & 31; 462811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 463811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif 464811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_LAND: 465811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_LOR: 466811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t1 = vl->val.u; 467811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t2 = 0; /* gcc */ 468811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 469811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser default: 470811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t1 = vl->val.u; 471811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t2 = vr->val.u; 472811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 474811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 475811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#define cmpop(op) (es->natural ? \ 476811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser (mksh_uari_t)(vl->val.u op vr->val.u) : \ 477811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser (mksh_uari_t)(vl->val.i op vr->val.i) \ 478811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser) 479811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 480811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* op calculation */ 4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch ((int)op) { 4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_TIMES: 4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_TIMESASN: 484811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 * t2; 4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 486811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_MOD: 487811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_MODASN: 488811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (es->natural) { 489811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = vl->val.u % vr->val.u; 490811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 491811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 492811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser goto signed_division; 4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_DIV: 4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_DIVASN: 495811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (es->natural) { 496811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = vl->val.u / vr->val.u; 497811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 498811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 499811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser signed_division: 500c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* 501811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * a / b = abs(a) / abs(b) * sgn((u)a^(u)b) 502c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser */ 503811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t3 = t1 / t2; 504811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_LEGACY_MODE 505811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = ((vl->val.u ^ vr->val.u) & 0x80000000) ? -t3 : t3; 506811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#else 507811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = ((t1 == vl->val.u ? 0 : 1) ^ 508811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser (t2 == vr->val.u ? 0 : 1)) ? -t3 : t3; 509c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 510811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (op == O_MOD || op == O_MODASN) { 511811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* 512811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * primitive modulo, to get the sign of 513811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * the result correct: 514811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * (a % b) = a - ((a / b) * b) 515811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * the subtraction and multiplication 516811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * are, amazingly enough, sign ignorant 517811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser */ 518811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = vl->val.u - (res * vr->val.u); 519811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_PLUS: 5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_PLUSASN: 523811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 + t2; 5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_MINUS: 5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_MINUSASN: 527811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 - t2; 528811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 529811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_LEGACY_MODE 530811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_ROL: 531811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_ROLASN: 532811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = (t1 << t2) | (t1 >> (32 - t2)); 5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 534811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_ROR: 535811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case O_RORASN: 536811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = (t1 >> t2) | (t1 << (32 - t2)); 537811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 538811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif 5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_LSHIFT: 5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_LSHIFTASN: 541811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 << t2; 5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_RSHIFT: 5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_RSHIFTASN: 545811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = es->natural || vl->val.i >= 0 ? 546811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser t1 >> t2 : 547811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ~(~t1 >> t2); 5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_LT: 550811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = cmpop(<); 5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_LE: 553811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = cmpop(<=); 5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_GT: 556811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = cmpop(>); 5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_GE: 559811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = cmpop(>=); 5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_EQ: 562811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 == t2; 5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_NE: 565811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 != t2; 5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_BAND: 5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_BANDASN: 569811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 & t2; 5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_BXOR: 5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_BXORASN: 573811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 ^ t2; 5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_BOR: 5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_BORASN: 577811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 | t2; 5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_LAND: 580811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!t1) 5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->noassign++; 5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vr = intvar(es, evalexpr(es, prec - 1)); 583811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 && vr->val.u; 584811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!t1) 5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->noassign--; 5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_LOR: 588811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (t1) 5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->noassign++; 5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vr = intvar(es, evalexpr(es, prec - 1)); 591811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t1 || vr->val.u; 592811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (t1) 5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->noassign--; 5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_ASN: 5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case O_COMMA: 597811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser res = t2; 5985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 600811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 601811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#undef cmpop 602811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (IS_ASSIGNOP(op)) { 604c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser vr->val.u = res; 6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!es->noassign) { 6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vasn->flag & INTEGER) 6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setint_v(vasn, vr, es->arith); 6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 609811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser setint(vasn, vr->val.i); 6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vl = vr; 612811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } else 613c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser vl->val.u = res; 6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (vl); 6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruexprtoken(Expr_state *es) 6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *cp = es->tokp; 6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *tvar; 6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 625811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* skip whitespace */ 6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru skip_spaces: 6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((c = *cp), ksh_isspace(c)) 6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++cp; 6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (es->tokp == es->expression && c == '#') { 6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* expression begins with # */ 631811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* switch to unsigned */ 632811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser es->natural = true; 6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++cp; 6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto skip_spaces; 6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->tokp = cp; 6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '\0') 6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->tok = END; 6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (ksh_isalphx(c)) { 6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; ksh_isalnux(c); c = *cp) 6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp++; 6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '[') { 64403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len; 6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = array_ref_len(cp); 6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (len == 0) 6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru evalerr(es, ET_STR, "missing ]"); 6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp += len; 6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (es->noassign) { 6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->val = tempvar(); 6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->val->flag |= EXPRLVALUE; 6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(tvar, es->tokp, cp - es->tokp, ATEMP); 6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->val = global(tvar); 6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(tvar, ATEMP); 6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->tok = VAR; 6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == '1' && cp[1] == '#') { 6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp += 2; 6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp += utf_ptradj(cp); 6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(tvar, es->tokp, cp - es->tokp, ATEMP); 6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto process_tvar; 6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL 6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == '\'') { 6675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++cp; 6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp += utf_ptradj(cp); 6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*cp++ != '\'') 6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru evalerr(es, ET_STR, 6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "multi-character character constant"); 6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 'x' -> 1#x (x = one multibyte character) */ 6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = cp - es->tokp; 6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tvar = alloc(c + /* NUL */ 1, ATEMP); 6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tvar[0] = '1'; 6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tvar[1] = '#'; 6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(tvar + 2, es->tokp + 1, c - 2); 6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tvar[c] = '\0'; 6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto process_tvar; 6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (ksh_isdigit(c)) { 6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (c != '_' && (ksh_isalnux(c) || c == '#')) 6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *cp++; 6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(tvar, es->tokp, --cp - es->tokp, ATEMP); 6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru process_tvar: 6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->val = tempvar(); 6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->val->flag &= ~INTEGER; 6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->val->type = 0; 6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->val->val.s = tvar; 6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (setint_v(es->val, es->val, es->arith) == NULL) 6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru evalerr(es, ET_BADLIT, tvar); 6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(tvar, ATEMP); 6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->tok = LIT; 6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i, n0; 6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; (n0 = opinfo[i].name[0]); i++) 6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == n0 && strncmp(cp, opinfo[i].name, 6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (size_t)opinfo[i].len) == 0) { 7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->tok = (enum token)i; 7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp += opinfo[i].len; 7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!n0) 7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->tok = BAD; 7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->tokp = cp; 7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruassign_check(Expr_state *es, enum token op, struct tbl *vasn) 7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 713c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (es->tok == END || !vasn || 7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (vasn->name[0] == '\0' && !(vasn->flag & EXPRLVALUE))) 7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru evalerr(es, ET_LVALUE, opinfo[(int)op].name); 7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (vasn->flag & RDONLY) 7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru evalerr(es, ET_RDONLY, opinfo[(int)op].name); 7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 720c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstruct tbl * 7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutempvar(void) 7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *vp; 7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp = alloc(sizeof(struct tbl), ATEMP); 7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->flag = ISSET|INTEGER; 7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->type = 0; 7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->areap = ATEMP; 7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->ua.hval = 0; 7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->val.i = 0; 7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->name[0] = '\0'; 7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (vp); 7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* cast (string) variable to temporary integer variable */ 7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct tbl * 7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruintvar(Expr_state *es, struct tbl *vp) 7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *vq; 7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* try to avoid replacing a temp var with another temp var */ 7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vp->name[0] == '\0' && 7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (vp->flag & (ISSET|INTEGER|EXPRLVALUE)) == (ISSET|INTEGER)) 7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (vp); 7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vq = tempvar(); 7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (setint_v(vq, vp, es->arith) == NULL) { 7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vp->flag & EXPRINEVAL) 7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru evalerr(es, ET_RECURSIVE, vp->name); 7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->evaling = vp; 7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->flag |= EXPRINEVAL; 7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru v_evaluate(vq, str_val(vp), KSH_UNWIND_ERROR, es->arith); 7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->flag &= ~EXPRINEVAL; 7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru es->evaling = NULL; 7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (vq); 7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * UTF-8 support code: high-level functions 7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 7655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutf_widthadj(const char *src, const char **dst) 7665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t len; 7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned int wc; 7695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int width; 7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!UTFMODE || (len = utf_mbtowc(&wc, src)) == (size_t)-1 || 7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc == 0) 7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = width = 1; 7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if ((width = utf_wcwidth(wc)) < 0) 7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* XXX use 2 for x_zotc3 here? */ 7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru width = 1; 7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (dst) 7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dst = src + len; 7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (width); 7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 78303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasize_t 7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutf_mbswidth(const char *s) 7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 78603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len, width = 0; 7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned int wc; 78803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int cw; 7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!UTFMODE) 7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (strlen(s)); 7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*s) 7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (((len = utf_mbtowc(&wc, s)) == (size_t)-1) || 7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((cw = utf_wcwidth(wc)) == -1)) { 7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s++; 7975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru width += 1; 7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 7995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s += len; 8005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru width += cw; 8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (width); 8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst char * 8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutf_skipcols(const char *p, int cols) 8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c = 0; 8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (c < cols) { 8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!*p) 8125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p + cols - c); 8135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c += utf_widthadj(p, &p); 8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusize_t 8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutf_ptradj(const char *src) 8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru register size_t n; 8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!UTFMODE || 8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *(const unsigned char *)(src) < 0xC2 || 8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (n = utf_mbtowc(NULL, src)) == (size_t)-1) 8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n = 1; 8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (n); 8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * UTF-8 support code: low-level functions 8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* CESU-8 multibyte and wide character conversion crafted for mksh */ 8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusize_t 8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutf_mbtowc(unsigned int *dst, const char *src) 8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *s = (const unsigned char *)src; 8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned int c, wc; 8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((wc = *s++) < 0x80) { 8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru out: 8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (dst != NULL) 8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dst = wc; 8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (wc ? ((const char *)s - src) : 0); 8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (wc < 0xC2 || wc >= 0xF0) 8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* < 0xC0: spurious second byte */ 8505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* < 0xC2: non-minimalistic mapping error in 2-byte seqs */ 8515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* > 0xEF: beyond BMP */ 8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto ilseq; 8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (wc < 0xE0) { 8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = (wc & 0x1F) << 6; 8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (((c = *s++) & 0xC0) != 0x80) 8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto ilseq; 8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc |= c & 0x3F; 8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto out; 8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = (wc & 0x0F) << 12; 8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (((c = *s++) & 0xC0) != 0x80) 8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto ilseq; 8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc |= (c & 0x3F) << 6; 8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (((c = *s++) & 0xC0) != 0x80) 8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto ilseq; 8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc |= c & 0x3F; 8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Check for non-minimalistic mapping error in 3-byte seqs */ 8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (wc >= 0x0800 && wc <= 0xFFFD) 8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto out; 8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ilseq: 8765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((size_t)(-1)); 8775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusize_t 8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruutf_wctomb(char *dst, unsigned int wc) 8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned char *d; 8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (wc < 0x80) { 8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dst = wc; 8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = (unsigned char *)dst; 8905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (wc < 0x0800) 8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = (wc >> 6) | 0xC0; 8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 8935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = ((wc = wc > 0xFFFD ? 0xFFFD : wc) >> 12) | 0xE0; 8945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = ((wc >> 6) & 0x3F) | 0x80; 8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *d++ = (wc & 0x3F) | 0x80; 8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((char *)d - dst); 8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 90003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 90103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Wrapper around access(2) because it says root can execute everything 90203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * on some operating systems. Does not set errno, no user needs it. Use 90303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * this iff mode can have the X_OK bit set, access otherwise. 90403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 90503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraint 90603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraksh_access(const char *fn, int mode) 90703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 90803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int rv; 90903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct stat sb; 91003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 91103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((rv = access(fn, mode)) == 0 && kshuid == 0 && (mode & X_OK) && 91203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (rv = stat(fn, &sb)) == 0 && !S_ISDIR(sb.st_mode) && 91303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) 91403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = -1; 91503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 91603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (rv); 91703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 918811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 919737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes/* From: X11/xc/programs/xterm/wcwidth.c,v 1.8 2014/06/24 19:53:53 tg Exp $ */ 920811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 921811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstruct mb_ucsrange { 922811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser unsigned short beg; 923811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser unsigned short end; 924811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser}; 925811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 926811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic int mb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems, 927737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes unsigned int val) MKSH_A_PURE; 928811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 929811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser/* 930737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes * Generated by MirOS: contrib/code/Snippets/eawparse,v 1.2 2013/11/30 13:45:17 tg Exp $ 931737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes * from the Unicode Character Database, Version 7.0.0 932811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser */ 933811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 934811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic const struct mb_ucsrange mb_ucs_combining[] = { 935811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0300, 0x036F }, 936811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0483, 0x0489 }, 937811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0591, 0x05BD }, 938811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x05BF, 0x05BF }, 939811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x05C1, 0x05C2 }, 940811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x05C4, 0x05C5 }, 941811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x05C7, 0x05C7 }, 942737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x0600, 0x0605 }, 943811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0610, 0x061A }, 944737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x061C, 0x061C }, 945811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x064B, 0x065F }, 946811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0670, 0x0670 }, 947811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x06D6, 0x06DD }, 948811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x06DF, 0x06E4 }, 949811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x06E7, 0x06E8 }, 950811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x06EA, 0x06ED }, 951811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x070F, 0x070F }, 952811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0711, 0x0711 }, 953811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0730, 0x074A }, 954811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x07A6, 0x07B0 }, 955811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x07EB, 0x07F3 }, 956811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0816, 0x0819 }, 957811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x081B, 0x0823 }, 958811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0825, 0x0827 }, 959811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0829, 0x082D }, 960811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0859, 0x085B }, 961737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x08E4, 0x0902 }, 962811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x093A, 0x093A }, 963811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x093C, 0x093C }, 964811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0941, 0x0948 }, 965811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x094D, 0x094D }, 966811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0951, 0x0957 }, 967811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0962, 0x0963 }, 968811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0981, 0x0981 }, 969811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x09BC, 0x09BC }, 970811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x09C1, 0x09C4 }, 971811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x09CD, 0x09CD }, 972811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x09E2, 0x09E3 }, 973811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0A01, 0x0A02 }, 974811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0A3C, 0x0A3C }, 975811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0A41, 0x0A42 }, 976811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0A47, 0x0A48 }, 977811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0A4B, 0x0A4D }, 978811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0A51, 0x0A51 }, 979811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0A70, 0x0A71 }, 980811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0A75, 0x0A75 }, 981811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0A81, 0x0A82 }, 982811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0ABC, 0x0ABC }, 983811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0AC1, 0x0AC5 }, 984811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0AC7, 0x0AC8 }, 985811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0ACD, 0x0ACD }, 986811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0AE2, 0x0AE3 }, 987811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0B01, 0x0B01 }, 988811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0B3C, 0x0B3C }, 989811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0B3F, 0x0B3F }, 990811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0B41, 0x0B44 }, 991811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0B4D, 0x0B4D }, 992811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0B56, 0x0B56 }, 993811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0B62, 0x0B63 }, 994811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0B82, 0x0B82 }, 995811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0BC0, 0x0BC0 }, 996811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0BCD, 0x0BCD }, 997737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x0C00, 0x0C00 }, 998811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0C3E, 0x0C40 }, 999811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0C46, 0x0C48 }, 1000811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0C4A, 0x0C4D }, 1001811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0C55, 0x0C56 }, 1002811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0C62, 0x0C63 }, 1003737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x0C81, 0x0C81 }, 1004811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0CBC, 0x0CBC }, 1005811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0CBF, 0x0CBF }, 1006811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0CC6, 0x0CC6 }, 1007811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0CCC, 0x0CCD }, 1008811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0CE2, 0x0CE3 }, 1009737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x0D01, 0x0D01 }, 1010811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0D41, 0x0D44 }, 1011811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0D4D, 0x0D4D }, 1012811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0D62, 0x0D63 }, 1013811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0DCA, 0x0DCA }, 1014811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0DD2, 0x0DD4 }, 1015811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0DD6, 0x0DD6 }, 1016811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0E31, 0x0E31 }, 1017811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0E34, 0x0E3A }, 1018811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0E47, 0x0E4E }, 1019811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0EB1, 0x0EB1 }, 1020811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0EB4, 0x0EB9 }, 1021811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0EBB, 0x0EBC }, 1022811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0EC8, 0x0ECD }, 1023811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0F18, 0x0F19 }, 1024811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0F35, 0x0F35 }, 1025811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0F37, 0x0F37 }, 1026811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0F39, 0x0F39 }, 1027811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0F71, 0x0F7E }, 1028811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0F80, 0x0F84 }, 1029811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0F86, 0x0F87 }, 1030811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0F8D, 0x0F97 }, 1031811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0F99, 0x0FBC }, 1032811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x0FC6, 0x0FC6 }, 1033811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x102D, 0x1030 }, 1034811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1032, 0x1037 }, 1035811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1039, 0x103A }, 1036811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x103D, 0x103E }, 1037811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1058, 0x1059 }, 1038811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x105E, 0x1060 }, 1039811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1071, 0x1074 }, 1040811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1082, 0x1082 }, 1041811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1085, 0x1086 }, 1042811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x108D, 0x108D }, 1043811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x109D, 0x109D }, 1044811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1160, 0x11FF }, 1045811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x135D, 0x135F }, 1046811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1712, 0x1714 }, 1047811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1732, 0x1734 }, 1048811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1752, 0x1753 }, 1049811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1772, 0x1773 }, 1050811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x17B4, 0x17B5 }, 1051811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x17B7, 0x17BD }, 1052811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x17C6, 0x17C6 }, 1053811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x17C9, 0x17D3 }, 1054811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x17DD, 0x17DD }, 1055737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x180B, 0x180E }, 1056811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x18A9, 0x18A9 }, 1057811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1920, 0x1922 }, 1058811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1927, 0x1928 }, 1059811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1932, 0x1932 }, 1060811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1939, 0x193B }, 1061811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1A17, 0x1A18 }, 1062737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x1A1B, 0x1A1B }, 1063811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1A56, 0x1A56 }, 1064811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1A58, 0x1A5E }, 1065811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1A60, 0x1A60 }, 1066811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1A62, 0x1A62 }, 1067811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1A65, 0x1A6C }, 1068811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1A73, 0x1A7C }, 1069811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1A7F, 0x1A7F }, 1070737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x1AB0, 0x1ABE }, 1071811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1B00, 0x1B03 }, 1072811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1B34, 0x1B34 }, 1073811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1B36, 0x1B3A }, 1074811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1B3C, 0x1B3C }, 1075811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1B42, 0x1B42 }, 1076811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1B6B, 0x1B73 }, 1077811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1B80, 0x1B81 }, 1078811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1BA2, 0x1BA5 }, 1079811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1BA8, 0x1BA9 }, 1080737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x1BAB, 0x1BAD }, 1081811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1BE6, 0x1BE6 }, 1082811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1BE8, 0x1BE9 }, 1083811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1BED, 0x1BED }, 1084811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1BEF, 0x1BF1 }, 1085811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1C2C, 0x1C33 }, 1086811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1C36, 0x1C37 }, 1087811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1CD0, 0x1CD2 }, 1088811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1CD4, 0x1CE0 }, 1089811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1CE2, 0x1CE8 }, 1090811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1CED, 0x1CED }, 1091811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1CF4, 0x1CF4 }, 1092737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x1CF8, 0x1CF9 }, 1093737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x1DC0, 0x1DF5 }, 1094811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1DFC, 0x1DFF }, 1095811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x200B, 0x200F }, 1096811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x202A, 0x202E }, 1097811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x2060, 0x2064 }, 1098737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0x2066, 0x206F }, 1099811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x20D0, 0x20F0 }, 1100811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x2CEF, 0x2CF1 }, 1101811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x2D7F, 0x2D7F }, 1102811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x2DE0, 0x2DFF }, 1103811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x302A, 0x302D }, 1104811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x3099, 0x309A }, 1105811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA66F, 0xA672 }, 1106811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA674, 0xA67D }, 1107811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA69F, 0xA69F }, 1108811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA6F0, 0xA6F1 }, 1109811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA802, 0xA802 }, 1110811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA806, 0xA806 }, 1111811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA80B, 0xA80B }, 1112811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA825, 0xA826 }, 1113811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA8C4, 0xA8C4 }, 1114811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA8E0, 0xA8F1 }, 1115811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA926, 0xA92D }, 1116811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA947, 0xA951 }, 1117811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA980, 0xA982 }, 1118811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA9B3, 0xA9B3 }, 1119811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA9B6, 0xA9B9 }, 1120811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA9BC, 0xA9BC }, 1121737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0xA9E5, 0xA9E5 }, 1122811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAA29, 0xAA2E }, 1123811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAA31, 0xAA32 }, 1124811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAA35, 0xAA36 }, 1125811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAA43, 0xAA43 }, 1126811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAA4C, 0xAA4C }, 1127737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0xAA7C, 0xAA7C }, 1128811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAAB0, 0xAAB0 }, 1129811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAAB2, 0xAAB4 }, 1130811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAAB7, 0xAAB8 }, 1131811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAABE, 0xAABF }, 1132811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAAC1, 0xAAC1 }, 1133811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAAEC, 0xAAED }, 1134811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAAF6, 0xAAF6 }, 1135811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xABE5, 0xABE5 }, 1136811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xABE8, 0xABE8 }, 1137811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xABED, 0xABED }, 1138811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xFB1E, 0xFB1E }, 1139811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xFE00, 0xFE0F }, 1140737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes { 0xFE20, 0xFE2D }, 1141811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xFEFF, 0xFEFF }, 1142811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xFFF9, 0xFFFB } 1143811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser}; 1144811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1145811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic const struct mb_ucsrange mb_ucs_fullwidth[] = { 1146811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x1100, 0x115F }, 1147811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x2329, 0x232A }, 1148811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x2E80, 0x303E }, 1149811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0x3040, 0xA4CF }, 1150811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xA960, 0xA97F }, 1151811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xAC00, 0xD7A3 }, 1152811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xF900, 0xFAFF }, 1153811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xFE10, 0xFE19 }, 1154811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xFE30, 0xFE6F }, 1155811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xFF00, 0xFF60 }, 1156811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser { 0xFFE0, 0xFFE6 } 1157811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser}; 1158811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1159811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser/* simple binary search in ranges, with bounds optimisation */ 1160811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic int 1161811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glasermb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems, unsigned int val) 1162811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser{ 1163811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser size_t min = 0, mid, max = elems; 1164811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1165811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (val < arr[min].beg || val > arr[max - 1].end) 1166811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (0); 1167811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1168811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser while (min < max) { 1169811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser mid = (min + max) / 2; 1170811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1171811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (val < arr[mid].beg) 1172811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser max = mid; 1173811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser else if (val > arr[mid].end) 1174811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser min = mid + 1; 1175811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser else 1176811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (1); 1177811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 1178811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (0); 1179811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser} 1180811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1181811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser/* Unix column width of a wide character (Unicode code point, really) */ 1182811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserint 1183811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserutf_wcwidth(unsigned int wc) 1184811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser{ 1185811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* except NUL, C0/C1 control characters and DEL yield -1 */ 1186811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (wc < 0x20 || (wc >= 0x7F && wc < 0xA0)) 1187811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (wc ? -1 : 0); 1188811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1189811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* combining characters use 0 screen columns */ 1190811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (mb_ucsbsearch(mb_ucs_combining, NELEM(mb_ucs_combining), wc)) 1191811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (0); 1192811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1193811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* all others use 1 or 2 screen columns */ 1194811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (mb_ucsbsearch(mb_ucs_fullwidth, NELEM(mb_ucs_fullwidth), wc)) 1195811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (2); 1196811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (1); 1197811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser} 1198