1c84f3f3cSopenharmony_ci/* $OpenBSD: expr.c,v 1.24 2014/12/08 14:26:31 otto Exp $ */ 2c84f3f3cSopenharmony_ci 3c84f3f3cSopenharmony_ci/*- 4c84f3f3cSopenharmony_ci * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 5c84f3f3cSopenharmony_ci * 2011, 2012, 2013, 2014, 2016, 2017, 2018, 2019 6c84f3f3cSopenharmony_ci * mirabilos <m@mirbsd.org> 7c84f3f3cSopenharmony_ci * 8c84f3f3cSopenharmony_ci * Provided that these terms and disclaimer and all copyright notices 9c84f3f3cSopenharmony_ci * are retained or reproduced in an accompanying document, permission 10c84f3f3cSopenharmony_ci * is granted to deal in this work without restriction, including un- 11c84f3f3cSopenharmony_ci * limited rights to use, publicly perform, distribute, sell, modify, 12c84f3f3cSopenharmony_ci * merge, give away, or sublicence. 13c84f3f3cSopenharmony_ci * 14c84f3f3cSopenharmony_ci * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 15c84f3f3cSopenharmony_ci * the utmost extent permitted by applicable law, neither express nor 16c84f3f3cSopenharmony_ci * implied; without malicious intent or gross negligence. In no event 17c84f3f3cSopenharmony_ci * may a licensor, author or contributor be held liable for indirect, 18c84f3f3cSopenharmony_ci * direct, other damage, loss, or other issues arising in any way out 19c84f3f3cSopenharmony_ci * of dealing in the work, even if advised of the possibility of such 20c84f3f3cSopenharmony_ci * damage or existence of a defect, except proven that it results out 21c84f3f3cSopenharmony_ci * of said person's immediate fault when using the work as intended. 22c84f3f3cSopenharmony_ci */ 23c84f3f3cSopenharmony_ci 24c84f3f3cSopenharmony_ci#include "sh.h" 25c84f3f3cSopenharmony_ci 26c84f3f3cSopenharmony_ci__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.108 2020/06/20 02:27:50 tg Exp $"); 27c84f3f3cSopenharmony_ci 28c84f3f3cSopenharmony_ci#define EXPRTOK_DEFNS 29c84f3f3cSopenharmony_ci#include "exprtok.h" 30c84f3f3cSopenharmony_ci 31c84f3f3cSopenharmony_ci/* precisions; used to be enum prec but we do arithmetics on it */ 32c84f3f3cSopenharmony_ci#define P_PRIMARY 0 /* VAR, LIT, (), ! ~ ++ -- */ 33c84f3f3cSopenharmony_ci#define P_MULT 1 /* * / % */ 34c84f3f3cSopenharmony_ci#define P_ADD 2 /* + - */ 35c84f3f3cSopenharmony_ci#define P_SHIFT 3 /* ^< ^> << >> */ 36c84f3f3cSopenharmony_ci#define P_RELATION 4 /* < <= > >= */ 37c84f3f3cSopenharmony_ci#define P_EQUALITY 5 /* == != */ 38c84f3f3cSopenharmony_ci#define P_BAND 6 /* & */ 39c84f3f3cSopenharmony_ci#define P_BXOR 7 /* ^ */ 40c84f3f3cSopenharmony_ci#define P_BOR 8 /* | */ 41c84f3f3cSopenharmony_ci#define P_LAND 9 /* && */ 42c84f3f3cSopenharmony_ci#define P_LOR 10 /* || */ 43c84f3f3cSopenharmony_ci#define P_TERN 11 /* ?: */ 44c84f3f3cSopenharmony_ci /* = += -= *= /= %= ^<= ^>= <<= >>= &= ^= |= */ 45c84f3f3cSopenharmony_ci#define P_ASSIGN 12 46c84f3f3cSopenharmony_ci#define P_COMMA 13 /* , */ 47c84f3f3cSopenharmony_ci#define MAX_PREC P_COMMA 48c84f3f3cSopenharmony_ci 49c84f3f3cSopenharmony_cienum token { 50c84f3f3cSopenharmony_ci#define EXPRTOK_ENUM 51c84f3f3cSopenharmony_ci#include "exprtok.h" 52c84f3f3cSopenharmony_ci}; 53c84f3f3cSopenharmony_ci 54c84f3f3cSopenharmony_cistatic const char opname[][4] = { 55c84f3f3cSopenharmony_ci#define EXPRTOK_NAME 56c84f3f3cSopenharmony_ci#include "exprtok.h" 57c84f3f3cSopenharmony_ci}; 58c84f3f3cSopenharmony_ci 59c84f3f3cSopenharmony_cistatic const uint8_t oplen[] = { 60c84f3f3cSopenharmony_ci#define EXPRTOK_LEN 61c84f3f3cSopenharmony_ci#include "exprtok.h" 62c84f3f3cSopenharmony_ci}; 63c84f3f3cSopenharmony_ci 64c84f3f3cSopenharmony_cistatic const uint8_t opprec[] = { 65c84f3f3cSopenharmony_ci#define EXPRTOK_PREC 66c84f3f3cSopenharmony_ci#include "exprtok.h" 67c84f3f3cSopenharmony_ci}; 68c84f3f3cSopenharmony_ci 69c84f3f3cSopenharmony_citypedef struct expr_state { 70c84f3f3cSopenharmony_ci /* expression being evaluated */ 71c84f3f3cSopenharmony_ci const char *expression; 72c84f3f3cSopenharmony_ci /* lexical position */ 73c84f3f3cSopenharmony_ci const char *tokp; 74c84f3f3cSopenharmony_ci /* value from token() */ 75c84f3f3cSopenharmony_ci struct tbl *val; 76c84f3f3cSopenharmony_ci /* variable that is being recursively expanded (EXPRINEVAL flag set) */ 77c84f3f3cSopenharmony_ci struct tbl *evaling; 78c84f3f3cSopenharmony_ci /* token from token() */ 79c84f3f3cSopenharmony_ci enum token tok; 80c84f3f3cSopenharmony_ci /* don't do assignments (for ?:, &&, ||) */ 81c84f3f3cSopenharmony_ci uint8_t noassign; 82c84f3f3cSopenharmony_ci /* evaluating an $(()) expression? */ 83c84f3f3cSopenharmony_ci bool arith; 84c84f3f3cSopenharmony_ci /* unsigned arithmetic calculation */ 85c84f3f3cSopenharmony_ci bool natural; 86c84f3f3cSopenharmony_ci} Expr_state; 87c84f3f3cSopenharmony_ci 88c84f3f3cSopenharmony_cienum error_type { 89c84f3f3cSopenharmony_ci ET_UNEXPECTED, ET_BADLIT, ET_RECURSIVE, 90c84f3f3cSopenharmony_ci ET_LVALUE, ET_RDONLY, ET_STR 91c84f3f3cSopenharmony_ci}; 92c84f3f3cSopenharmony_ci 93c84f3f3cSopenharmony_cistatic void evalerr(Expr_state *, enum error_type, const char *) 94c84f3f3cSopenharmony_ci MKSH_A_NORETURN; 95c84f3f3cSopenharmony_cistatic struct tbl *evalexpr(Expr_state *, unsigned int); 96c84f3f3cSopenharmony_cistatic void exprtoken(Expr_state *); 97c84f3f3cSopenharmony_cistatic struct tbl *do_ppmm(Expr_state *, enum token, struct tbl *, bool); 98c84f3f3cSopenharmony_cistatic void assign_check(Expr_state *, enum token, struct tbl *); 99c84f3f3cSopenharmony_cistatic struct tbl *intvar(Expr_state *, struct tbl *); 100c84f3f3cSopenharmony_ci 101c84f3f3cSopenharmony_ci/* 102c84f3f3cSopenharmony_ci * parse and evaluate expression 103c84f3f3cSopenharmony_ci */ 104c84f3f3cSopenharmony_ciint 105c84f3f3cSopenharmony_cievaluate(const char *expr, mksh_ari_t *rval, int error_ok, bool arith) 106c84f3f3cSopenharmony_ci{ 107c84f3f3cSopenharmony_ci struct tbl v; 108c84f3f3cSopenharmony_ci int ret; 109c84f3f3cSopenharmony_ci 110c84f3f3cSopenharmony_ci v.flag = DEFINED | INTEGER; 111c84f3f3cSopenharmony_ci v.type = 0; 112c84f3f3cSopenharmony_ci ret = v_evaluate(&v, expr, error_ok, arith); 113c84f3f3cSopenharmony_ci *rval = v.val.i; 114c84f3f3cSopenharmony_ci return (ret); 115c84f3f3cSopenharmony_ci} 116c84f3f3cSopenharmony_ci 117c84f3f3cSopenharmony_ci/* 118c84f3f3cSopenharmony_ci * parse and evaluate expression, storing result in vp. 119c84f3f3cSopenharmony_ci */ 120c84f3f3cSopenharmony_ciint 121c84f3f3cSopenharmony_civ_evaluate(struct tbl *vp, const char *expr, volatile int error_ok, 122c84f3f3cSopenharmony_ci bool arith) 123c84f3f3cSopenharmony_ci{ 124c84f3f3cSopenharmony_ci struct tbl *v; 125c84f3f3cSopenharmony_ci Expr_state curstate; 126c84f3f3cSopenharmony_ci Expr_state * const es = &curstate; 127c84f3f3cSopenharmony_ci int i; 128c84f3f3cSopenharmony_ci 129c84f3f3cSopenharmony_ci /* save state to allow recursive calls */ 130c84f3f3cSopenharmony_ci memset(&curstate, 0, sizeof(curstate)); 131c84f3f3cSopenharmony_ci curstate.expression = curstate.tokp = expr; 132c84f3f3cSopenharmony_ci curstate.tok = BAD; 133c84f3f3cSopenharmony_ci curstate.arith = arith; 134c84f3f3cSopenharmony_ci 135c84f3f3cSopenharmony_ci newenv(E_ERRH); 136c84f3f3cSopenharmony_ci if ((i = kshsetjmp(e->jbuf))) { 137c84f3f3cSopenharmony_ci /* Clear EXPRINEVAL in of any variables we were playing with */ 138c84f3f3cSopenharmony_ci if (curstate.evaling) 139c84f3f3cSopenharmony_ci curstate.evaling->flag &= ~EXPRINEVAL; 140c84f3f3cSopenharmony_ci quitenv(NULL); 141c84f3f3cSopenharmony_ci if (i == LAEXPR) { 142c84f3f3cSopenharmony_ci if (error_ok == KSH_RETURN_ERROR) 143c84f3f3cSopenharmony_ci return (0); 144c84f3f3cSopenharmony_ci errorfz(); 145c84f3f3cSopenharmony_ci } 146c84f3f3cSopenharmony_ci unwind(i); 147c84f3f3cSopenharmony_ci /* NOTREACHED */ 148c84f3f3cSopenharmony_ci } 149c84f3f3cSopenharmony_ci 150c84f3f3cSopenharmony_ci exprtoken(es); 151c84f3f3cSopenharmony_ci if (es->tok == END) { 152c84f3f3cSopenharmony_ci es->tok = LIT; 153c84f3f3cSopenharmony_ci es->val = tempvar(""); 154c84f3f3cSopenharmony_ci } 155c84f3f3cSopenharmony_ci v = intvar(es, evalexpr(es, MAX_PREC)); 156c84f3f3cSopenharmony_ci 157c84f3f3cSopenharmony_ci if (es->tok != END) 158c84f3f3cSopenharmony_ci evalerr(es, ET_UNEXPECTED, NULL); 159c84f3f3cSopenharmony_ci 160c84f3f3cSopenharmony_ci if (es->arith && es->natural) 161c84f3f3cSopenharmony_ci vp->flag |= INT_U; 162c84f3f3cSopenharmony_ci if (vp->flag & INTEGER) 163c84f3f3cSopenharmony_ci setint_v(vp, v, es->arith); 164c84f3f3cSopenharmony_ci else 165c84f3f3cSopenharmony_ci /* can fail if readonly */ 166c84f3f3cSopenharmony_ci setstr(vp, str_val(v), error_ok); 167c84f3f3cSopenharmony_ci 168c84f3f3cSopenharmony_ci quitenv(NULL); 169c84f3f3cSopenharmony_ci 170c84f3f3cSopenharmony_ci return (1); 171c84f3f3cSopenharmony_ci} 172c84f3f3cSopenharmony_ci 173c84f3f3cSopenharmony_cistatic void 174c84f3f3cSopenharmony_cievalerr(Expr_state *es, enum error_type type, const char *str) 175c84f3f3cSopenharmony_ci{ 176c84f3f3cSopenharmony_ci char tbuf[2]; 177c84f3f3cSopenharmony_ci const char *s; 178c84f3f3cSopenharmony_ci 179c84f3f3cSopenharmony_ci es->arith = false; 180c84f3f3cSopenharmony_ci switch (type) { 181c84f3f3cSopenharmony_ci case ET_UNEXPECTED: 182c84f3f3cSopenharmony_ci switch (es->tok) { 183c84f3f3cSopenharmony_ci case VAR: 184c84f3f3cSopenharmony_ci s = es->val->name; 185c84f3f3cSopenharmony_ci break; 186c84f3f3cSopenharmony_ci case LIT: 187c84f3f3cSopenharmony_ci s = str_val(es->val); 188c84f3f3cSopenharmony_ci break; 189c84f3f3cSopenharmony_ci case END: 190c84f3f3cSopenharmony_ci s = "end of expression"; 191c84f3f3cSopenharmony_ci break; 192c84f3f3cSopenharmony_ci case BAD: 193c84f3f3cSopenharmony_ci tbuf[0] = *es->tokp; 194c84f3f3cSopenharmony_ci tbuf[1] = '\0'; 195c84f3f3cSopenharmony_ci s = tbuf; 196c84f3f3cSopenharmony_ci break; 197c84f3f3cSopenharmony_ci default: 198c84f3f3cSopenharmony_ci s = opname[(int)es->tok]; 199c84f3f3cSopenharmony_ci } 200c84f3f3cSopenharmony_ci warningf(true, Tf_sD_s_qs, es->expression, 201c84f3f3cSopenharmony_ci Tunexpected, s); 202c84f3f3cSopenharmony_ci break; 203c84f3f3cSopenharmony_ci 204c84f3f3cSopenharmony_ci case ET_BADLIT: 205c84f3f3cSopenharmony_ci warningf(true, Tf_sD_s_qs, es->expression, 206c84f3f3cSopenharmony_ci Tbadnum, str); 207c84f3f3cSopenharmony_ci break; 208c84f3f3cSopenharmony_ci 209c84f3f3cSopenharmony_ci case ET_RECURSIVE: 210c84f3f3cSopenharmony_ci warningf(true, Tf_sD_s_qs, es->expression, 211c84f3f3cSopenharmony_ci "expression recurses on parameter", str); 212c84f3f3cSopenharmony_ci break; 213c84f3f3cSopenharmony_ci 214c84f3f3cSopenharmony_ci case ET_LVALUE: 215c84f3f3cSopenharmony_ci warningf(true, Tf_sD_s_s, 216c84f3f3cSopenharmony_ci es->expression, str, "requires lvalue"); 217c84f3f3cSopenharmony_ci break; 218c84f3f3cSopenharmony_ci 219c84f3f3cSopenharmony_ci case ET_RDONLY: 220c84f3f3cSopenharmony_ci warningf(true, Tf_sD_s_s, 221c84f3f3cSopenharmony_ci es->expression, str, "applied to read-only variable"); 222c84f3f3cSopenharmony_ci break; 223c84f3f3cSopenharmony_ci 224c84f3f3cSopenharmony_ci default: /* keep gcc happy */ 225c84f3f3cSopenharmony_ci case ET_STR: 226c84f3f3cSopenharmony_ci warningf(true, Tf_sD_s, es->expression, str); 227c84f3f3cSopenharmony_ci break; 228c84f3f3cSopenharmony_ci } 229c84f3f3cSopenharmony_ci unwind(LAEXPR); 230c84f3f3cSopenharmony_ci} 231c84f3f3cSopenharmony_ci 232c84f3f3cSopenharmony_ci/* do a ++ or -- operation */ 233c84f3f3cSopenharmony_cistatic struct tbl * 234c84f3f3cSopenharmony_cido_ppmm(Expr_state *es, enum token op, struct tbl *vasn, bool is_prefix) 235c84f3f3cSopenharmony_ci{ 236c84f3f3cSopenharmony_ci struct tbl *vl; 237c84f3f3cSopenharmony_ci mksh_uari_t oval; 238c84f3f3cSopenharmony_ci 239c84f3f3cSopenharmony_ci assign_check(es, op, vasn); 240c84f3f3cSopenharmony_ci 241c84f3f3cSopenharmony_ci vl = intvar(es, vasn); 242c84f3f3cSopenharmony_ci oval = vl->val.u; 243c84f3f3cSopenharmony_ci if (op == O_PLUSPLUS) 244c84f3f3cSopenharmony_ci ++vl->val.u; 245c84f3f3cSopenharmony_ci else 246c84f3f3cSopenharmony_ci --vl->val.u; 247c84f3f3cSopenharmony_ci if (!es->noassign) { 248c84f3f3cSopenharmony_ci if (vasn->flag & INTEGER) 249c84f3f3cSopenharmony_ci setint_v(vasn, vl, es->arith); 250c84f3f3cSopenharmony_ci else 251c84f3f3cSopenharmony_ci setint(vasn, vl->val.i); 252c84f3f3cSopenharmony_ci } 253c84f3f3cSopenharmony_ci if (!is_prefix) 254c84f3f3cSopenharmony_ci /* undo the increment/decrement */ 255c84f3f3cSopenharmony_ci vl->val.u = oval; 256c84f3f3cSopenharmony_ci 257c84f3f3cSopenharmony_ci return (vl); 258c84f3f3cSopenharmony_ci} 259c84f3f3cSopenharmony_ci 260c84f3f3cSopenharmony_cistatic struct tbl * 261c84f3f3cSopenharmony_cievalexpr(Expr_state *es, unsigned int prec) 262c84f3f3cSopenharmony_ci{ 263c84f3f3cSopenharmony_ci struct tbl *vl, *vr = NULL, *vasn; 264c84f3f3cSopenharmony_ci enum token op; 265c84f3f3cSopenharmony_ci mksh_uari_t res = 0, t1, t2, t3; 266c84f3f3cSopenharmony_ci 267c84f3f3cSopenharmony_ci if (prec == P_PRIMARY) { 268c84f3f3cSopenharmony_ci switch ((int)(op = es->tok)) { 269c84f3f3cSopenharmony_ci case O_BNOT: 270c84f3f3cSopenharmony_ci case O_LNOT: 271c84f3f3cSopenharmony_ci case O_MINUS: 272c84f3f3cSopenharmony_ci case O_PLUS: 273c84f3f3cSopenharmony_ci exprtoken(es); 274c84f3f3cSopenharmony_ci vl = intvar(es, evalexpr(es, P_PRIMARY)); 275c84f3f3cSopenharmony_ci switch ((int)op) { 276c84f3f3cSopenharmony_ci case O_BNOT: 277c84f3f3cSopenharmony_ci vl->val.u = ~vl->val.u; 278c84f3f3cSopenharmony_ci break; 279c84f3f3cSopenharmony_ci case O_LNOT: 280c84f3f3cSopenharmony_ci vl->val.u = !vl->val.u; 281c84f3f3cSopenharmony_ci break; 282c84f3f3cSopenharmony_ci case O_MINUS: 283c84f3f3cSopenharmony_ci vl->val.u = -vl->val.u; 284c84f3f3cSopenharmony_ci break; 285c84f3f3cSopenharmony_ci case O_PLUS: 286c84f3f3cSopenharmony_ci /* nop */ 287c84f3f3cSopenharmony_ci break; 288c84f3f3cSopenharmony_ci } 289c84f3f3cSopenharmony_ci break; 290c84f3f3cSopenharmony_ci 291c84f3f3cSopenharmony_ci case OPEN_PAREN: 292c84f3f3cSopenharmony_ci exprtoken(es); 293c84f3f3cSopenharmony_ci vl = evalexpr(es, MAX_PREC); 294c84f3f3cSopenharmony_ci if (es->tok != CLOSE_PAREN) 295c84f3f3cSopenharmony_ci evalerr(es, ET_STR, "missing )"); 296c84f3f3cSopenharmony_ci exprtoken(es); 297c84f3f3cSopenharmony_ci break; 298c84f3f3cSopenharmony_ci 299c84f3f3cSopenharmony_ci case O_PLUSPLUS: 300c84f3f3cSopenharmony_ci case O_MINUSMINUS: 301c84f3f3cSopenharmony_ci exprtoken(es); 302c84f3f3cSopenharmony_ci vl = do_ppmm(es, op, es->val, true); 303c84f3f3cSopenharmony_ci exprtoken(es); 304c84f3f3cSopenharmony_ci break; 305c84f3f3cSopenharmony_ci 306c84f3f3cSopenharmony_ci case VAR: 307c84f3f3cSopenharmony_ci case LIT: 308c84f3f3cSopenharmony_ci vl = es->val; 309c84f3f3cSopenharmony_ci exprtoken(es); 310c84f3f3cSopenharmony_ci break; 311c84f3f3cSopenharmony_ci 312c84f3f3cSopenharmony_ci default: 313c84f3f3cSopenharmony_ci evalerr(es, ET_UNEXPECTED, NULL); 314c84f3f3cSopenharmony_ci /* NOTREACHED */ 315c84f3f3cSopenharmony_ci } 316c84f3f3cSopenharmony_ci 317c84f3f3cSopenharmony_ci if (es->tok == O_PLUSPLUS || es->tok == O_MINUSMINUS) { 318c84f3f3cSopenharmony_ci vl = do_ppmm(es, es->tok, vl, false); 319c84f3f3cSopenharmony_ci exprtoken(es); 320c84f3f3cSopenharmony_ci } 321c84f3f3cSopenharmony_ci 322c84f3f3cSopenharmony_ci return (vl); 323c84f3f3cSopenharmony_ci /* prec == P_PRIMARY */ 324c84f3f3cSopenharmony_ci } 325c84f3f3cSopenharmony_ci 326c84f3f3cSopenharmony_ci vl = evalexpr(es, prec - 1); 327c84f3f3cSopenharmony_ci while ((int)(op = es->tok) >= (int)O_EQ && (int)op <= (int)O_COMMA && 328c84f3f3cSopenharmony_ci opprec[(int)op] == prec) { 329c84f3f3cSopenharmony_ci switch ((int)op) { 330c84f3f3cSopenharmony_ci case O_TERN: 331c84f3f3cSopenharmony_ci case O_LAND: 332c84f3f3cSopenharmony_ci case O_LOR: 333c84f3f3cSopenharmony_ci break; 334c84f3f3cSopenharmony_ci default: 335c84f3f3cSopenharmony_ci exprtoken(es); 336c84f3f3cSopenharmony_ci } 337c84f3f3cSopenharmony_ci 338c84f3f3cSopenharmony_ci vasn = vl; 339c84f3f3cSopenharmony_ci if (op != O_ASN) 340c84f3f3cSopenharmony_ci /* vl may not have a value yet */ 341c84f3f3cSopenharmony_ci vl = intvar(es, vl); 342c84f3f3cSopenharmony_ci if (IS_ASSIGNOP(op)) { 343c84f3f3cSopenharmony_ci if (!es->noassign) 344c84f3f3cSopenharmony_ci assign_check(es, op, vasn); 345c84f3f3cSopenharmony_ci vr = intvar(es, evalexpr(es, P_ASSIGN)); 346c84f3f3cSopenharmony_ci } else if (op == O_TERN) { 347c84f3f3cSopenharmony_ci bool ev = vl->val.u != 0; 348c84f3f3cSopenharmony_ci 349c84f3f3cSopenharmony_ci if (!ev) 350c84f3f3cSopenharmony_ci es->noassign++; 351c84f3f3cSopenharmony_ci exprtoken(es); 352c84f3f3cSopenharmony_ci vl = evalexpr(es, MAX_PREC); 353c84f3f3cSopenharmony_ci if (!ev) 354c84f3f3cSopenharmony_ci es->noassign--; 355c84f3f3cSopenharmony_ci if (es->tok != CTERN) 356c84f3f3cSopenharmony_ci evalerr(es, ET_STR, "missing :"); 357c84f3f3cSopenharmony_ci if (ev) 358c84f3f3cSopenharmony_ci es->noassign++; 359c84f3f3cSopenharmony_ci exprtoken(es); 360c84f3f3cSopenharmony_ci vr = evalexpr(es, P_TERN); 361c84f3f3cSopenharmony_ci if (ev) 362c84f3f3cSopenharmony_ci es->noassign--; 363c84f3f3cSopenharmony_ci vl = ev ? vl : vr; 364c84f3f3cSopenharmony_ci continue; 365c84f3f3cSopenharmony_ci } else if (op != O_LAND && op != O_LOR) 366c84f3f3cSopenharmony_ci vr = intvar(es, evalexpr(es, prec - 1)); 367c84f3f3cSopenharmony_ci 368c84f3f3cSopenharmony_ci /* common ops setup */ 369c84f3f3cSopenharmony_ci switch ((int)op) { 370c84f3f3cSopenharmony_ci case O_DIV: 371c84f3f3cSopenharmony_ci case O_DIVASN: 372c84f3f3cSopenharmony_ci case O_MOD: 373c84f3f3cSopenharmony_ci case O_MODASN: 374c84f3f3cSopenharmony_ci if (vr->val.u == 0) { 375c84f3f3cSopenharmony_ci if (!es->noassign) 376c84f3f3cSopenharmony_ci evalerr(es, ET_STR, "zero divisor"); 377c84f3f3cSopenharmony_ci vr->val.u = 1; 378c84f3f3cSopenharmony_ci } 379c84f3f3cSopenharmony_ci /* calculate the absolute values */ 380c84f3f3cSopenharmony_ci t1 = vl->val.i < 0 ? -vl->val.u : vl->val.u; 381c84f3f3cSopenharmony_ci t2 = vr->val.i < 0 ? -vr->val.u : vr->val.u; 382c84f3f3cSopenharmony_ci break; 383c84f3f3cSopenharmony_ci#ifndef MKSH_LEGACY_MODE 384c84f3f3cSopenharmony_ci case O_LSHIFT: 385c84f3f3cSopenharmony_ci case O_LSHIFTASN: 386c84f3f3cSopenharmony_ci case O_RSHIFT: 387c84f3f3cSopenharmony_ci case O_RSHIFTASN: 388c84f3f3cSopenharmony_ci case O_ROL: 389c84f3f3cSopenharmony_ci case O_ROLASN: 390c84f3f3cSopenharmony_ci case O_ROR: 391c84f3f3cSopenharmony_ci case O_RORASN: 392c84f3f3cSopenharmony_ci t1 = vl->val.u; 393c84f3f3cSopenharmony_ci t2 = vr->val.u & 31; 394c84f3f3cSopenharmony_ci break; 395c84f3f3cSopenharmony_ci#endif 396c84f3f3cSopenharmony_ci case O_LAND: 397c84f3f3cSopenharmony_ci case O_LOR: 398c84f3f3cSopenharmony_ci t1 = vl->val.u; 399c84f3f3cSopenharmony_ci t2 = 0; /* gcc */ 400c84f3f3cSopenharmony_ci break; 401c84f3f3cSopenharmony_ci default: 402c84f3f3cSopenharmony_ci t1 = vl->val.u; 403c84f3f3cSopenharmony_ci t2 = vr->val.u; 404c84f3f3cSopenharmony_ci break; 405c84f3f3cSopenharmony_ci } 406c84f3f3cSopenharmony_ci 407c84f3f3cSopenharmony_ci#define cmpop(op) (es->natural ? \ 408c84f3f3cSopenharmony_ci (mksh_uari_t)(vl->val.u op vr->val.u) : \ 409c84f3f3cSopenharmony_ci (mksh_uari_t)(vl->val.i op vr->val.i) \ 410c84f3f3cSopenharmony_ci) 411c84f3f3cSopenharmony_ci 412c84f3f3cSopenharmony_ci /* op calculation */ 413c84f3f3cSopenharmony_ci switch ((int)op) { 414c84f3f3cSopenharmony_ci case O_TIMES: 415c84f3f3cSopenharmony_ci case O_TIMESASN: 416c84f3f3cSopenharmony_ci res = t1 * t2; 417c84f3f3cSopenharmony_ci break; 418c84f3f3cSopenharmony_ci case O_MOD: 419c84f3f3cSopenharmony_ci case O_MODASN: 420c84f3f3cSopenharmony_ci if (es->natural) { 421c84f3f3cSopenharmony_ci res = vl->val.u % vr->val.u; 422c84f3f3cSopenharmony_ci break; 423c84f3f3cSopenharmony_ci } 424c84f3f3cSopenharmony_ci goto signed_division; 425c84f3f3cSopenharmony_ci case O_DIV: 426c84f3f3cSopenharmony_ci case O_DIVASN: 427c84f3f3cSopenharmony_ci if (es->natural) { 428c84f3f3cSopenharmony_ci res = vl->val.u / vr->val.u; 429c84f3f3cSopenharmony_ci break; 430c84f3f3cSopenharmony_ci } 431c84f3f3cSopenharmony_ci signed_division: 432c84f3f3cSopenharmony_ci /* 433c84f3f3cSopenharmony_ci * a / b = abs(a) / abs(b) * sgn((u)a^(u)b) 434c84f3f3cSopenharmony_ci */ 435c84f3f3cSopenharmony_ci t3 = t1 / t2; 436c84f3f3cSopenharmony_ci#ifndef MKSH_LEGACY_MODE 437c84f3f3cSopenharmony_ci res = ((vl->val.u ^ vr->val.u) & 0x80000000) ? -t3 : t3; 438c84f3f3cSopenharmony_ci#else 439c84f3f3cSopenharmony_ci res = ((t1 == vl->val.u ? 0 : 1) ^ 440c84f3f3cSopenharmony_ci (t2 == vr->val.u ? 0 : 1)) ? -t3 : t3; 441c84f3f3cSopenharmony_ci#endif 442c84f3f3cSopenharmony_ci if (op == O_MOD || op == O_MODASN) { 443c84f3f3cSopenharmony_ci /* 444c84f3f3cSopenharmony_ci * primitive modulo, to get the sign of 445c84f3f3cSopenharmony_ci * the result correct: 446c84f3f3cSopenharmony_ci * (a % b) = a - ((a / b) * b) 447c84f3f3cSopenharmony_ci * the subtraction and multiplication 448c84f3f3cSopenharmony_ci * are, amazingly enough, sign ignorant 449c84f3f3cSopenharmony_ci */ 450c84f3f3cSopenharmony_ci res = vl->val.u - (res * vr->val.u); 451c84f3f3cSopenharmony_ci } 452c84f3f3cSopenharmony_ci break; 453c84f3f3cSopenharmony_ci case O_PLUS: 454c84f3f3cSopenharmony_ci case O_PLUSASN: 455c84f3f3cSopenharmony_ci res = t1 + t2; 456c84f3f3cSopenharmony_ci break; 457c84f3f3cSopenharmony_ci case O_MINUS: 458c84f3f3cSopenharmony_ci case O_MINUSASN: 459c84f3f3cSopenharmony_ci res = t1 - t2; 460c84f3f3cSopenharmony_ci break; 461c84f3f3cSopenharmony_ci#ifndef MKSH_LEGACY_MODE 462c84f3f3cSopenharmony_ci case O_ROL: 463c84f3f3cSopenharmony_ci case O_ROLASN: 464c84f3f3cSopenharmony_ci res = (t1 << t2) | (t1 >> (32 - t2)); 465c84f3f3cSopenharmony_ci break; 466c84f3f3cSopenharmony_ci case O_ROR: 467c84f3f3cSopenharmony_ci case O_RORASN: 468c84f3f3cSopenharmony_ci res = (t1 >> t2) | (t1 << (32 - t2)); 469c84f3f3cSopenharmony_ci break; 470c84f3f3cSopenharmony_ci#endif 471c84f3f3cSopenharmony_ci case O_LSHIFT: 472c84f3f3cSopenharmony_ci case O_LSHIFTASN: 473c84f3f3cSopenharmony_ci res = t1 << t2; 474c84f3f3cSopenharmony_ci break; 475c84f3f3cSopenharmony_ci case O_RSHIFT: 476c84f3f3cSopenharmony_ci case O_RSHIFTASN: 477c84f3f3cSopenharmony_ci res = es->natural || vl->val.i >= 0 ? 478c84f3f3cSopenharmony_ci t1 >> t2 : 479c84f3f3cSopenharmony_ci ~(~t1 >> t2); 480c84f3f3cSopenharmony_ci break; 481c84f3f3cSopenharmony_ci case O_LT: 482c84f3f3cSopenharmony_ci res = cmpop(<); 483c84f3f3cSopenharmony_ci break; 484c84f3f3cSopenharmony_ci case O_LE: 485c84f3f3cSopenharmony_ci res = cmpop(<=); 486c84f3f3cSopenharmony_ci break; 487c84f3f3cSopenharmony_ci case O_GT: 488c84f3f3cSopenharmony_ci res = cmpop(>); 489c84f3f3cSopenharmony_ci break; 490c84f3f3cSopenharmony_ci case O_GE: 491c84f3f3cSopenharmony_ci res = cmpop(>=); 492c84f3f3cSopenharmony_ci break; 493c84f3f3cSopenharmony_ci case O_EQ: 494c84f3f3cSopenharmony_ci res = t1 == t2; 495c84f3f3cSopenharmony_ci break; 496c84f3f3cSopenharmony_ci case O_NE: 497c84f3f3cSopenharmony_ci res = t1 != t2; 498c84f3f3cSopenharmony_ci break; 499c84f3f3cSopenharmony_ci case O_BAND: 500c84f3f3cSopenharmony_ci case O_BANDASN: 501c84f3f3cSopenharmony_ci res = t1 & t2; 502c84f3f3cSopenharmony_ci break; 503c84f3f3cSopenharmony_ci case O_BXOR: 504c84f3f3cSopenharmony_ci case O_BXORASN: 505c84f3f3cSopenharmony_ci res = t1 ^ t2; 506c84f3f3cSopenharmony_ci break; 507c84f3f3cSopenharmony_ci case O_BOR: 508c84f3f3cSopenharmony_ci case O_BORASN: 509c84f3f3cSopenharmony_ci res = t1 | t2; 510c84f3f3cSopenharmony_ci break; 511c84f3f3cSopenharmony_ci case O_LAND: 512c84f3f3cSopenharmony_ci if (!t1) 513c84f3f3cSopenharmony_ci es->noassign++; 514c84f3f3cSopenharmony_ci exprtoken(es); 515c84f3f3cSopenharmony_ci vr = intvar(es, evalexpr(es, prec - 1)); 516c84f3f3cSopenharmony_ci res = t1 && vr->val.u; 517c84f3f3cSopenharmony_ci if (!t1) 518c84f3f3cSopenharmony_ci es->noassign--; 519c84f3f3cSopenharmony_ci break; 520c84f3f3cSopenharmony_ci case O_LOR: 521c84f3f3cSopenharmony_ci if (t1) 522c84f3f3cSopenharmony_ci es->noassign++; 523c84f3f3cSopenharmony_ci exprtoken(es); 524c84f3f3cSopenharmony_ci vr = intvar(es, evalexpr(es, prec - 1)); 525c84f3f3cSopenharmony_ci res = t1 || vr->val.u; 526c84f3f3cSopenharmony_ci if (t1) 527c84f3f3cSopenharmony_ci es->noassign--; 528c84f3f3cSopenharmony_ci break; 529c84f3f3cSopenharmony_ci case O_ASN: 530c84f3f3cSopenharmony_ci case O_COMMA: 531c84f3f3cSopenharmony_ci res = t2; 532c84f3f3cSopenharmony_ci break; 533c84f3f3cSopenharmony_ci } 534c84f3f3cSopenharmony_ci 535c84f3f3cSopenharmony_ci#undef cmpop 536c84f3f3cSopenharmony_ci 537c84f3f3cSopenharmony_ci if (IS_ASSIGNOP(op)) { 538c84f3f3cSopenharmony_ci vr->val.u = res; 539c84f3f3cSopenharmony_ci if (!es->noassign) { 540c84f3f3cSopenharmony_ci if (vasn->flag & INTEGER) 541c84f3f3cSopenharmony_ci setint_v(vasn, vr, es->arith); 542c84f3f3cSopenharmony_ci else 543c84f3f3cSopenharmony_ci setint(vasn, vr->val.i); 544c84f3f3cSopenharmony_ci } 545c84f3f3cSopenharmony_ci vl = vr; 546c84f3f3cSopenharmony_ci } else 547c84f3f3cSopenharmony_ci vl->val.u = res; 548c84f3f3cSopenharmony_ci } 549c84f3f3cSopenharmony_ci return (vl); 550c84f3f3cSopenharmony_ci} 551c84f3f3cSopenharmony_ci 552c84f3f3cSopenharmony_cistatic void 553c84f3f3cSopenharmony_ciexprtoken(Expr_state *es) 554c84f3f3cSopenharmony_ci{ 555c84f3f3cSopenharmony_ci const char *cp = es->tokp; 556c84f3f3cSopenharmony_ci int c; 557c84f3f3cSopenharmony_ci char *tvar; 558c84f3f3cSopenharmony_ci 559c84f3f3cSopenharmony_ci /* skip whitespace */ 560c84f3f3cSopenharmony_ci skip_spaces: 561c84f3f3cSopenharmony_ci --cp; 562c84f3f3cSopenharmony_ci do { 563c84f3f3cSopenharmony_ci c = ord(*++cp); 564c84f3f3cSopenharmony_ci } while (ctype(c, C_SPACE)); 565c84f3f3cSopenharmony_ci if (es->tokp == es->expression && (unsigned int)c == ORD('#')) { 566c84f3f3cSopenharmony_ci /* expression begins with # */ 567c84f3f3cSopenharmony_ci /* switch to unsigned */ 568c84f3f3cSopenharmony_ci es->natural = true; 569c84f3f3cSopenharmony_ci ++cp; 570c84f3f3cSopenharmony_ci goto skip_spaces; 571c84f3f3cSopenharmony_ci } 572c84f3f3cSopenharmony_ci es->tokp = cp; 573c84f3f3cSopenharmony_ci 574c84f3f3cSopenharmony_ci if (c == '\0') 575c84f3f3cSopenharmony_ci es->tok = END; 576c84f3f3cSopenharmony_ci else if (ctype(c, C_ALPHX)) { 577c84f3f3cSopenharmony_ci do { 578c84f3f3cSopenharmony_ci c = ord(*++cp); 579c84f3f3cSopenharmony_ci } while (ctype(c, C_ALNUX)); 580c84f3f3cSopenharmony_ci if ((unsigned int)c == ORD('[')) { 581c84f3f3cSopenharmony_ci size_t len; 582c84f3f3cSopenharmony_ci 583c84f3f3cSopenharmony_ci len = array_ref_len(cp); 584c84f3f3cSopenharmony_ci if (len == 0) 585c84f3f3cSopenharmony_ci evalerr(es, ET_STR, "missing ]"); 586c84f3f3cSopenharmony_ci cp += len; 587c84f3f3cSopenharmony_ci } 588c84f3f3cSopenharmony_ci if (es->noassign) { 589c84f3f3cSopenharmony_ci es->val = tempvar(""); 590c84f3f3cSopenharmony_ci es->val->flag |= EXPRLVALUE; 591c84f3f3cSopenharmony_ci } else { 592c84f3f3cSopenharmony_ci strndupx(tvar, es->tokp, cp - es->tokp, ATEMP); 593c84f3f3cSopenharmony_ci es->val = global(tvar); 594c84f3f3cSopenharmony_ci afree(tvar, ATEMP); 595c84f3f3cSopenharmony_ci } 596c84f3f3cSopenharmony_ci es->tok = VAR; 597c84f3f3cSopenharmony_ci } else if (c == '1' && cp[1] == '#') { 598c84f3f3cSopenharmony_ci cp += 2; 599c84f3f3cSopenharmony_ci if (*cp) 600c84f3f3cSopenharmony_ci cp += utf_ptradj(cp); 601c84f3f3cSopenharmony_ci strndupx(tvar, es->tokp, cp - es->tokp, ATEMP); 602c84f3f3cSopenharmony_ci goto process_tvar; 603c84f3f3cSopenharmony_ci#ifndef MKSH_SMALL 604c84f3f3cSopenharmony_ci } else if (c == '\'') { 605c84f3f3cSopenharmony_ci if (*++cp == '\0') { 606c84f3f3cSopenharmony_ci es->tok = END; 607c84f3f3cSopenharmony_ci evalerr(es, ET_UNEXPECTED, NULL); 608c84f3f3cSopenharmony_ci } 609c84f3f3cSopenharmony_ci cp += utf_ptradj(cp); 610c84f3f3cSopenharmony_ci if (*cp++ != '\'') 611c84f3f3cSopenharmony_ci evalerr(es, ET_STR, 612c84f3f3cSopenharmony_ci "multi-character character constant"); 613c84f3f3cSopenharmony_ci /* 'x' -> 1#x (x = one multibyte character) */ 614c84f3f3cSopenharmony_ci c = cp - es->tokp; 615c84f3f3cSopenharmony_ci tvar = alloc(c + /* NUL */ 1, ATEMP); 616c84f3f3cSopenharmony_ci tvar[0] = '1'; 617c84f3f3cSopenharmony_ci tvar[1] = '#'; 618c84f3f3cSopenharmony_ci memcpy(tvar + 2, es->tokp + 1, c - 2); 619c84f3f3cSopenharmony_ci tvar[c] = '\0'; 620c84f3f3cSopenharmony_ci goto process_tvar; 621c84f3f3cSopenharmony_ci#endif 622c84f3f3cSopenharmony_ci } else if (ctype(c, C_DIGIT)) { 623c84f3f3cSopenharmony_ci while (ctype(c, C_ALNUM | C_HASH)) 624c84f3f3cSopenharmony_ci c = ord(*cp++); 625c84f3f3cSopenharmony_ci strndupx(tvar, es->tokp, --cp - es->tokp, ATEMP); 626c84f3f3cSopenharmony_ci process_tvar: 627c84f3f3cSopenharmony_ci es->val = tempvar(""); 628c84f3f3cSopenharmony_ci es->val->flag &= ~INTEGER; 629c84f3f3cSopenharmony_ci es->val->type = 0; 630c84f3f3cSopenharmony_ci es->val->val.s = tvar; 631c84f3f3cSopenharmony_ci if (setint_v(es->val, es->val, es->arith) == NULL) 632c84f3f3cSopenharmony_ci evalerr(es, ET_BADLIT, tvar); 633c84f3f3cSopenharmony_ci afree(tvar, ATEMP); 634c84f3f3cSopenharmony_ci es->tok = LIT; 635c84f3f3cSopenharmony_ci } else { 636c84f3f3cSopenharmony_ci int i, n0; 637c84f3f3cSopenharmony_ci 638c84f3f3cSopenharmony_ci for (i = 0; (n0 = ord(opname[i][0])); i++) 639c84f3f3cSopenharmony_ci if (c == n0 && strncmp(cp, opname[i], 640c84f3f3cSopenharmony_ci (size_t)oplen[i]) == 0) { 641c84f3f3cSopenharmony_ci es->tok = (enum token)i; 642c84f3f3cSopenharmony_ci cp += oplen[i]; 643c84f3f3cSopenharmony_ci break; 644c84f3f3cSopenharmony_ci } 645c84f3f3cSopenharmony_ci if (!n0) 646c84f3f3cSopenharmony_ci es->tok = BAD; 647c84f3f3cSopenharmony_ci } 648c84f3f3cSopenharmony_ci es->tokp = cp; 649c84f3f3cSopenharmony_ci} 650c84f3f3cSopenharmony_ci 651c84f3f3cSopenharmony_cistatic void 652c84f3f3cSopenharmony_ciassign_check(Expr_state *es, enum token op, struct tbl *vasn) 653c84f3f3cSopenharmony_ci{ 654c84f3f3cSopenharmony_ci if (es->tok == END || !vasn || 655c84f3f3cSopenharmony_ci (vasn->name[0] == '\0' && !(vasn->flag & EXPRLVALUE))) 656c84f3f3cSopenharmony_ci evalerr(es, ET_LVALUE, opname[(int)op]); 657c84f3f3cSopenharmony_ci else if (vasn->flag & RDONLY) 658c84f3f3cSopenharmony_ci evalerr(es, ET_RDONLY, opname[(int)op]); 659c84f3f3cSopenharmony_ci} 660c84f3f3cSopenharmony_ci 661c84f3f3cSopenharmony_cistruct tbl * 662c84f3f3cSopenharmony_citempvar(const char *vname) 663c84f3f3cSopenharmony_ci{ 664c84f3f3cSopenharmony_ci struct tbl *vp; 665c84f3f3cSopenharmony_ci size_t vsize; 666c84f3f3cSopenharmony_ci 667c84f3f3cSopenharmony_ci vsize = strlen(vname) + 1; 668c84f3f3cSopenharmony_ci vp = alloc(offsetof(struct tbl, name[0]) + vsize, ATEMP); 669c84f3f3cSopenharmony_ci memcpy(vp->name, vname, vsize); 670c84f3f3cSopenharmony_ci vp->flag = ISSET|INTEGER; 671c84f3f3cSopenharmony_ci vp->type = 0; 672c84f3f3cSopenharmony_ci vp->areap = ATEMP; 673c84f3f3cSopenharmony_ci vp->ua.hval = 0; 674c84f3f3cSopenharmony_ci vp->val.i = 0; 675c84f3f3cSopenharmony_ci return (vp); 676c84f3f3cSopenharmony_ci} 677c84f3f3cSopenharmony_ci 678c84f3f3cSopenharmony_ci/* cast (string) variable to temporary integer variable */ 679c84f3f3cSopenharmony_cistatic struct tbl * 680c84f3f3cSopenharmony_ciintvar(Expr_state *es, struct tbl *vp) 681c84f3f3cSopenharmony_ci{ 682c84f3f3cSopenharmony_ci struct tbl *vq; 683c84f3f3cSopenharmony_ci 684c84f3f3cSopenharmony_ci /* try to avoid replacing a temp var with another temp var */ 685c84f3f3cSopenharmony_ci if (vp->name[0] == '\0' && 686c84f3f3cSopenharmony_ci (vp->flag & (ISSET|INTEGER|EXPRLVALUE)) == (ISSET|INTEGER)) 687c84f3f3cSopenharmony_ci return (vp); 688c84f3f3cSopenharmony_ci 689c84f3f3cSopenharmony_ci vq = tempvar(""); 690c84f3f3cSopenharmony_ci if (setint_v(vq, vp, es->arith) == NULL) { 691c84f3f3cSopenharmony_ci if (vp->flag & EXPRINEVAL) 692c84f3f3cSopenharmony_ci evalerr(es, ET_RECURSIVE, vp->name); 693c84f3f3cSopenharmony_ci es->evaling = vp; 694c84f3f3cSopenharmony_ci vp->flag |= EXPRINEVAL; 695c84f3f3cSopenharmony_ci v_evaluate(vq, str_val(vp), KSH_UNWIND_ERROR, es->arith); 696c84f3f3cSopenharmony_ci vp->flag &= ~EXPRINEVAL; 697c84f3f3cSopenharmony_ci es->evaling = NULL; 698c84f3f3cSopenharmony_ci } 699c84f3f3cSopenharmony_ci return (vq); 700c84f3f3cSopenharmony_ci} 701c84f3f3cSopenharmony_ci 702c84f3f3cSopenharmony_ci 703c84f3f3cSopenharmony_ci/* 704c84f3f3cSopenharmony_ci * UTF-8 support code: high-level functions 705c84f3f3cSopenharmony_ci */ 706c84f3f3cSopenharmony_ci 707c84f3f3cSopenharmony_ciint 708c84f3f3cSopenharmony_ciutf_widthadj(const char *src, const char **dst) 709c84f3f3cSopenharmony_ci{ 710c84f3f3cSopenharmony_ci size_t len; 711c84f3f3cSopenharmony_ci unsigned int wc; 712c84f3f3cSopenharmony_ci int width; 713c84f3f3cSopenharmony_ci 714c84f3f3cSopenharmony_ci if (!UTFMODE || (len = utf_mbtowc(&wc, src)) == (size_t)-1 || 715c84f3f3cSopenharmony_ci wc == 0) 716c84f3f3cSopenharmony_ci len = width = 1; 717c84f3f3cSopenharmony_ci else if ((width = utf_wcwidth(wc)) < 0) 718c84f3f3cSopenharmony_ci /* XXX use 2 for x_zotc3 here? */ 719c84f3f3cSopenharmony_ci width = 1; 720c84f3f3cSopenharmony_ci 721c84f3f3cSopenharmony_ci if (dst) 722c84f3f3cSopenharmony_ci *dst = src + len; 723c84f3f3cSopenharmony_ci return (width); 724c84f3f3cSopenharmony_ci} 725c84f3f3cSopenharmony_ci 726c84f3f3cSopenharmony_cisize_t 727c84f3f3cSopenharmony_ciutf_mbswidth(const char *s) 728c84f3f3cSopenharmony_ci{ 729c84f3f3cSopenharmony_ci size_t len, width = 0; 730c84f3f3cSopenharmony_ci unsigned int wc; 731c84f3f3cSopenharmony_ci int cw; 732c84f3f3cSopenharmony_ci 733c84f3f3cSopenharmony_ci if (!UTFMODE) 734c84f3f3cSopenharmony_ci return (strlen(s)); 735c84f3f3cSopenharmony_ci 736c84f3f3cSopenharmony_ci while (*s) 737c84f3f3cSopenharmony_ci if (((len = utf_mbtowc(&wc, s)) == (size_t)-1) || 738c84f3f3cSopenharmony_ci ((cw = utf_wcwidth(wc)) == -1)) { 739c84f3f3cSopenharmony_ci s++; 740c84f3f3cSopenharmony_ci width += 1; 741c84f3f3cSopenharmony_ci } else { 742c84f3f3cSopenharmony_ci s += len; 743c84f3f3cSopenharmony_ci width += cw; 744c84f3f3cSopenharmony_ci } 745c84f3f3cSopenharmony_ci return (width); 746c84f3f3cSopenharmony_ci} 747c84f3f3cSopenharmony_ci 748c84f3f3cSopenharmony_ciconst char * 749c84f3f3cSopenharmony_ciutf_skipcols(const char *p, int cols, int *colp) 750c84f3f3cSopenharmony_ci{ 751c84f3f3cSopenharmony_ci int c = 0; 752c84f3f3cSopenharmony_ci const char *q; 753c84f3f3cSopenharmony_ci 754c84f3f3cSopenharmony_ci while (c < cols) { 755c84f3f3cSopenharmony_ci if (!*p) { 756c84f3f3cSopenharmony_ci /* end of input; special handling for edit.c */ 757c84f3f3cSopenharmony_ci if (!colp) 758c84f3f3cSopenharmony_ci return (p + cols - c); 759c84f3f3cSopenharmony_ci *colp = c; 760c84f3f3cSopenharmony_ci return (p); 761c84f3f3cSopenharmony_ci } 762c84f3f3cSopenharmony_ci c += utf_widthadj(p, &p); 763c84f3f3cSopenharmony_ci } 764c84f3f3cSopenharmony_ci if (UTFMODE) 765c84f3f3cSopenharmony_ci while (utf_widthadj(p, &q) == 0) 766c84f3f3cSopenharmony_ci p = q; 767c84f3f3cSopenharmony_ci if (colp) 768c84f3f3cSopenharmony_ci *colp = c; 769c84f3f3cSopenharmony_ci return (p); 770c84f3f3cSopenharmony_ci} 771c84f3f3cSopenharmony_ci 772c84f3f3cSopenharmony_cisize_t 773c84f3f3cSopenharmony_ciutf_ptradj(const char *src) 774c84f3f3cSopenharmony_ci{ 775c84f3f3cSopenharmony_ci register size_t n; 776c84f3f3cSopenharmony_ci 777c84f3f3cSopenharmony_ci if (!UTFMODE || rtt2asc(*src) < 0xC2 || 778c84f3f3cSopenharmony_ci (n = utf_mbtowc(NULL, src)) == (size_t)-1) 779c84f3f3cSopenharmony_ci n = 1; 780c84f3f3cSopenharmony_ci return (n); 781c84f3f3cSopenharmony_ci} 782c84f3f3cSopenharmony_ci 783c84f3f3cSopenharmony_ci/* 784c84f3f3cSopenharmony_ci * UTF-8 support code: low-level functions 785c84f3f3cSopenharmony_ci */ 786c84f3f3cSopenharmony_ci 787c84f3f3cSopenharmony_ci/* CESU-8 multibyte and wide character conversion crafted for mksh */ 788c84f3f3cSopenharmony_ci 789c84f3f3cSopenharmony_cisize_t 790c84f3f3cSopenharmony_ciutf_mbtowc(unsigned int *dst, const char *src) 791c84f3f3cSopenharmony_ci{ 792c84f3f3cSopenharmony_ci const unsigned char *s = (const unsigned char *)src; 793c84f3f3cSopenharmony_ci unsigned int c, wc; 794c84f3f3cSopenharmony_ci 795c84f3f3cSopenharmony_ci if ((wc = ord(rtt2asc(*s++))) < 0x80) { 796c84f3f3cSopenharmony_ci out: 797c84f3f3cSopenharmony_ci if (dst != NULL) 798c84f3f3cSopenharmony_ci *dst = wc; 799c84f3f3cSopenharmony_ci return (wc ? ((const char *)s - src) : 0); 800c84f3f3cSopenharmony_ci } 801c84f3f3cSopenharmony_ci if (wc < 0xC2 || wc >= 0xF0) 802c84f3f3cSopenharmony_ci /* < 0xC0: spurious second byte */ 803c84f3f3cSopenharmony_ci /* < 0xC2: non-minimalistic mapping error in 2-byte seqs */ 804c84f3f3cSopenharmony_ci /* > 0xEF: beyond BMP */ 805c84f3f3cSopenharmony_ci goto ilseq; 806c84f3f3cSopenharmony_ci 807c84f3f3cSopenharmony_ci if (wc < 0xE0) { 808c84f3f3cSopenharmony_ci wc = (wc & 0x1F) << 6; 809c84f3f3cSopenharmony_ci if (((c = ord(rtt2asc(*s++))) & 0xC0) != 0x80) 810c84f3f3cSopenharmony_ci goto ilseq; 811c84f3f3cSopenharmony_ci wc |= c & 0x3F; 812c84f3f3cSopenharmony_ci goto out; 813c84f3f3cSopenharmony_ci } 814c84f3f3cSopenharmony_ci 815c84f3f3cSopenharmony_ci wc = (wc & 0x0F) << 12; 816c84f3f3cSopenharmony_ci 817c84f3f3cSopenharmony_ci if (((c = ord(rtt2asc(*s++))) & 0xC0) != 0x80) 818c84f3f3cSopenharmony_ci goto ilseq; 819c84f3f3cSopenharmony_ci wc |= (c & 0x3F) << 6; 820c84f3f3cSopenharmony_ci 821c84f3f3cSopenharmony_ci if (((c = ord(rtt2asc(*s++))) & 0xC0) != 0x80) 822c84f3f3cSopenharmony_ci goto ilseq; 823c84f3f3cSopenharmony_ci wc |= c & 0x3F; 824c84f3f3cSopenharmony_ci 825c84f3f3cSopenharmony_ci /* Check for non-minimalistic mapping error in 3-byte seqs */ 826c84f3f3cSopenharmony_ci if (wc >= 0x0800 && wc <= 0xFFFD) 827c84f3f3cSopenharmony_ci goto out; 828c84f3f3cSopenharmony_ci ilseq: 829c84f3f3cSopenharmony_ci return ((size_t)(-1)); 830c84f3f3cSopenharmony_ci} 831c84f3f3cSopenharmony_ci 832c84f3f3cSopenharmony_cisize_t 833c84f3f3cSopenharmony_ciutf_wctomb(char *dst, unsigned int wc) 834c84f3f3cSopenharmony_ci{ 835c84f3f3cSopenharmony_ci unsigned char *d; 836c84f3f3cSopenharmony_ci 837c84f3f3cSopenharmony_ci if (wc < 0x80) { 838c84f3f3cSopenharmony_ci *dst = asc2rtt(wc); 839c84f3f3cSopenharmony_ci return (1); 840c84f3f3cSopenharmony_ci } 841c84f3f3cSopenharmony_ci 842c84f3f3cSopenharmony_ci d = (unsigned char *)dst; 843c84f3f3cSopenharmony_ci if (wc < 0x0800) 844c84f3f3cSopenharmony_ci *d++ = asc2rtt((wc >> 6) | 0xC0); 845c84f3f3cSopenharmony_ci else { 846c84f3f3cSopenharmony_ci *d++ = asc2rtt(((wc = wc > 0xFFFD ? 0xFFFD : wc) >> 12) | 0xE0); 847c84f3f3cSopenharmony_ci *d++ = asc2rtt(((wc >> 6) & 0x3F) | 0x80); 848c84f3f3cSopenharmony_ci } 849c84f3f3cSopenharmony_ci *d++ = asc2rtt((wc & 0x3F) | 0x80); 850c84f3f3cSopenharmony_ci return ((char *)d - dst); 851c84f3f3cSopenharmony_ci} 852c84f3f3cSopenharmony_ci 853c84f3f3cSopenharmony_ci/* 854c84f3f3cSopenharmony_ci * Wrapper around access(2) because it says root can execute everything 855c84f3f3cSopenharmony_ci * on some operating systems. Does not set errno, no user needs it. Use 856c84f3f3cSopenharmony_ci * this iff mode can have the X_OK bit set, access otherwise. 857c84f3f3cSopenharmony_ci */ 858c84f3f3cSopenharmony_ciint 859c84f3f3cSopenharmony_ciksh_access(const char *fn, int mode) 860c84f3f3cSopenharmony_ci{ 861c84f3f3cSopenharmony_ci#ifdef __OS2__ 862c84f3f3cSopenharmony_ci return (access_ex(access, fn, mode)); 863c84f3f3cSopenharmony_ci#else 864c84f3f3cSopenharmony_ci int rv; 865c84f3f3cSopenharmony_ci struct stat sb; 866c84f3f3cSopenharmony_ci 867c84f3f3cSopenharmony_ci if ((rv = access(fn, mode)) == 0 && (mode & X_OK) && 868c84f3f3cSopenharmony_ci (kshuid == 0 || ksheuid == 0) && 869c84f3f3cSopenharmony_ci (rv = stat(fn, &sb)) == 0 && !S_ISDIR(sb.st_mode) && 870c84f3f3cSopenharmony_ci (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) 871c84f3f3cSopenharmony_ci rv = -1; 872c84f3f3cSopenharmony_ci 873c84f3f3cSopenharmony_ci return (rv); 874c84f3f3cSopenharmony_ci#endif 875c84f3f3cSopenharmony_ci} 876c84f3f3cSopenharmony_ci 877c84f3f3cSopenharmony_ci#ifndef MIRBSD_BOOTFLOPPY 878c84f3f3cSopenharmony_ci/* From: X11/xc/programs/xterm/wcwidth.c,v 1.10 */ 879c84f3f3cSopenharmony_ci 880c84f3f3cSopenharmony_cistruct mb_ucsrange { 881c84f3f3cSopenharmony_ci unsigned short beg; 882c84f3f3cSopenharmony_ci unsigned short end; 883c84f3f3cSopenharmony_ci}; 884c84f3f3cSopenharmony_ci 885c84f3f3cSopenharmony_cistatic int mb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems, 886c84f3f3cSopenharmony_ci unsigned int val) MKSH_A_PURE; 887c84f3f3cSopenharmony_ci 888c84f3f3cSopenharmony_ci/* 889c84f3f3cSopenharmony_ci * Generated from the UCD 13.0.0 - see /usr/share/doc/legal/LICENCE-BSD - by 890c84f3f3cSopenharmony_ci * MirOS: contrib/code/Snippets/eawparse,v 1.15 2020/06/15 20:31:13 tg Exp $ 891c84f3f3cSopenharmony_ci */ 892c84f3f3cSopenharmony_ci 893c84f3f3cSopenharmony_ci/*- 894c84f3f3cSopenharmony_ci * Parts Copyright © 1991–2020 Unicode, Inc. All rights reserved. 895c84f3f3cSopenharmony_ci * Distributed under the Terms of Use in 896c84f3f3cSopenharmony_ci * https://www.unicode.org/copyright.html. 897c84f3f3cSopenharmony_ci * 898c84f3f3cSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 899c84f3f3cSopenharmony_ci * a copy of the Unicode data files and any associated documentation 900c84f3f3cSopenharmony_ci * (the "Data Files") or Unicode software and any associated documentation 901c84f3f3cSopenharmony_ci * (the "Software") to deal in the Data Files or Software 902c84f3f3cSopenharmony_ci * without restriction, including without limitation the rights to use, 903c84f3f3cSopenharmony_ci * copy, modify, merge, publish, distribute, and/or sell copies of 904c84f3f3cSopenharmony_ci * the Data Files or Software, and to permit persons to whom the Data Files 905c84f3f3cSopenharmony_ci * or Software are furnished to do so, provided that either 906c84f3f3cSopenharmony_ci * (a) this copyright and permission notice appear with all copies 907c84f3f3cSopenharmony_ci * of the Data Files or Software, or 908c84f3f3cSopenharmony_ci * (b) this copyright and permission notice appear in associated 909c84f3f3cSopenharmony_ci * Documentation. 910c84f3f3cSopenharmony_ci * 911c84f3f3cSopenharmony_ci * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF 912c84f3f3cSopenharmony_ci * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 913c84f3f3cSopenharmony_ci * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 914c84f3f3cSopenharmony_ci * NONINFRINGEMENT OF THIRD PARTY RIGHTS. 915c84f3f3cSopenharmony_ci * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS 916c84f3f3cSopenharmony_ci * NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL 917c84f3f3cSopenharmony_ci * DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 918c84f3f3cSopenharmony_ci * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 919c84f3f3cSopenharmony_ci * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 920c84f3f3cSopenharmony_ci * PERFORMANCE OF THE DATA FILES OR SOFTWARE. 921c84f3f3cSopenharmony_ci * 922c84f3f3cSopenharmony_ci * Except as contained in this notice, the name of a copyright holder 923c84f3f3cSopenharmony_ci * shall not be used in advertising or otherwise to promote the sale, 924c84f3f3cSopenharmony_ci * use or other dealings in these Data Files or Software without prior 925c84f3f3cSopenharmony_ci * written authorization of the copyright holder. 926c84f3f3cSopenharmony_ci */ 927c84f3f3cSopenharmony_ci 928c84f3f3cSopenharmony_cistatic const struct mb_ucsrange mb_ucs_combining[] = { 929c84f3f3cSopenharmony_ci { 0x0300, 0x036F }, 930c84f3f3cSopenharmony_ci { 0x0483, 0x0489 }, 931c84f3f3cSopenharmony_ci { 0x0591, 0x05BD }, 932c84f3f3cSopenharmony_ci { 0x05BF, 0x05BF }, 933c84f3f3cSopenharmony_ci { 0x05C1, 0x05C2 }, 934c84f3f3cSopenharmony_ci { 0x05C4, 0x05C5 }, 935c84f3f3cSopenharmony_ci { 0x05C7, 0x05C7 }, 936c84f3f3cSopenharmony_ci { 0x0610, 0x061A }, 937c84f3f3cSopenharmony_ci { 0x061C, 0x061C }, 938c84f3f3cSopenharmony_ci { 0x064B, 0x065F }, 939c84f3f3cSopenharmony_ci { 0x0670, 0x0670 }, 940c84f3f3cSopenharmony_ci { 0x06D6, 0x06DC }, 941c84f3f3cSopenharmony_ci { 0x06DF, 0x06E4 }, 942c84f3f3cSopenharmony_ci { 0x06E7, 0x06E8 }, 943c84f3f3cSopenharmony_ci { 0x06EA, 0x06ED }, 944c84f3f3cSopenharmony_ci { 0x0711, 0x0711 }, 945c84f3f3cSopenharmony_ci { 0x0730, 0x074A }, 946c84f3f3cSopenharmony_ci { 0x07A6, 0x07B0 }, 947c84f3f3cSopenharmony_ci { 0x07EB, 0x07F3 }, 948c84f3f3cSopenharmony_ci { 0x07FD, 0x07FD }, 949c84f3f3cSopenharmony_ci { 0x0816, 0x0819 }, 950c84f3f3cSopenharmony_ci { 0x081B, 0x0823 }, 951c84f3f3cSopenharmony_ci { 0x0825, 0x0827 }, 952c84f3f3cSopenharmony_ci { 0x0829, 0x082D }, 953c84f3f3cSopenharmony_ci { 0x0859, 0x085B }, 954c84f3f3cSopenharmony_ci { 0x08D3, 0x08E1 }, 955c84f3f3cSopenharmony_ci { 0x08E3, 0x0902 }, 956c84f3f3cSopenharmony_ci { 0x093A, 0x093A }, 957c84f3f3cSopenharmony_ci { 0x093C, 0x093C }, 958c84f3f3cSopenharmony_ci { 0x0941, 0x0948 }, 959c84f3f3cSopenharmony_ci { 0x094D, 0x094D }, 960c84f3f3cSopenharmony_ci { 0x0951, 0x0957 }, 961c84f3f3cSopenharmony_ci { 0x0962, 0x0963 }, 962c84f3f3cSopenharmony_ci { 0x0981, 0x0981 }, 963c84f3f3cSopenharmony_ci { 0x09BC, 0x09BC }, 964c84f3f3cSopenharmony_ci { 0x09C1, 0x09C4 }, 965c84f3f3cSopenharmony_ci { 0x09CD, 0x09CD }, 966c84f3f3cSopenharmony_ci { 0x09E2, 0x09E3 }, 967c84f3f3cSopenharmony_ci { 0x09FE, 0x09FE }, 968c84f3f3cSopenharmony_ci { 0x0A01, 0x0A02 }, 969c84f3f3cSopenharmony_ci { 0x0A3C, 0x0A3C }, 970c84f3f3cSopenharmony_ci { 0x0A41, 0x0A42 }, 971c84f3f3cSopenharmony_ci { 0x0A47, 0x0A48 }, 972c84f3f3cSopenharmony_ci { 0x0A4B, 0x0A4D }, 973c84f3f3cSopenharmony_ci { 0x0A51, 0x0A51 }, 974c84f3f3cSopenharmony_ci { 0x0A70, 0x0A71 }, 975c84f3f3cSopenharmony_ci { 0x0A75, 0x0A75 }, 976c84f3f3cSopenharmony_ci { 0x0A81, 0x0A82 }, 977c84f3f3cSopenharmony_ci { 0x0ABC, 0x0ABC }, 978c84f3f3cSopenharmony_ci { 0x0AC1, 0x0AC5 }, 979c84f3f3cSopenharmony_ci { 0x0AC7, 0x0AC8 }, 980c84f3f3cSopenharmony_ci { 0x0ACD, 0x0ACD }, 981c84f3f3cSopenharmony_ci { 0x0AE2, 0x0AE3 }, 982c84f3f3cSopenharmony_ci { 0x0AFA, 0x0AFF }, 983c84f3f3cSopenharmony_ci { 0x0B01, 0x0B01 }, 984c84f3f3cSopenharmony_ci { 0x0B3C, 0x0B3C }, 985c84f3f3cSopenharmony_ci { 0x0B3F, 0x0B3F }, 986c84f3f3cSopenharmony_ci { 0x0B41, 0x0B44 }, 987c84f3f3cSopenharmony_ci { 0x0B4D, 0x0B4D }, 988c84f3f3cSopenharmony_ci { 0x0B55, 0x0B56 }, 989c84f3f3cSopenharmony_ci { 0x0B62, 0x0B63 }, 990c84f3f3cSopenharmony_ci { 0x0B82, 0x0B82 }, 991c84f3f3cSopenharmony_ci { 0x0BC0, 0x0BC0 }, 992c84f3f3cSopenharmony_ci { 0x0BCD, 0x0BCD }, 993c84f3f3cSopenharmony_ci { 0x0C00, 0x0C00 }, 994c84f3f3cSopenharmony_ci { 0x0C04, 0x0C04 }, 995c84f3f3cSopenharmony_ci { 0x0C3E, 0x0C40 }, 996c84f3f3cSopenharmony_ci { 0x0C46, 0x0C48 }, 997c84f3f3cSopenharmony_ci { 0x0C4A, 0x0C4D }, 998c84f3f3cSopenharmony_ci { 0x0C55, 0x0C56 }, 999c84f3f3cSopenharmony_ci { 0x0C62, 0x0C63 }, 1000c84f3f3cSopenharmony_ci { 0x0C81, 0x0C81 }, 1001c84f3f3cSopenharmony_ci { 0x0CBC, 0x0CBC }, 1002c84f3f3cSopenharmony_ci { 0x0CBF, 0x0CBF }, 1003c84f3f3cSopenharmony_ci { 0x0CC6, 0x0CC6 }, 1004c84f3f3cSopenharmony_ci { 0x0CCC, 0x0CCD }, 1005c84f3f3cSopenharmony_ci { 0x0CE2, 0x0CE3 }, 1006c84f3f3cSopenharmony_ci { 0x0D00, 0x0D01 }, 1007c84f3f3cSopenharmony_ci { 0x0D3B, 0x0D3C }, 1008c84f3f3cSopenharmony_ci { 0x0D41, 0x0D44 }, 1009c84f3f3cSopenharmony_ci { 0x0D4D, 0x0D4D }, 1010c84f3f3cSopenharmony_ci { 0x0D62, 0x0D63 }, 1011c84f3f3cSopenharmony_ci { 0x0D81, 0x0D81 }, 1012c84f3f3cSopenharmony_ci { 0x0DCA, 0x0DCA }, 1013c84f3f3cSopenharmony_ci { 0x0DD2, 0x0DD4 }, 1014c84f3f3cSopenharmony_ci { 0x0DD6, 0x0DD6 }, 1015c84f3f3cSopenharmony_ci { 0x0E31, 0x0E31 }, 1016c84f3f3cSopenharmony_ci { 0x0E34, 0x0E3A }, 1017c84f3f3cSopenharmony_ci { 0x0E47, 0x0E4E }, 1018c84f3f3cSopenharmony_ci { 0x0EB1, 0x0EB1 }, 1019c84f3f3cSopenharmony_ci { 0x0EB4, 0x0EBC }, 1020c84f3f3cSopenharmony_ci { 0x0EC8, 0x0ECD }, 1021c84f3f3cSopenharmony_ci { 0x0F18, 0x0F19 }, 1022c84f3f3cSopenharmony_ci { 0x0F35, 0x0F35 }, 1023c84f3f3cSopenharmony_ci { 0x0F37, 0x0F37 }, 1024c84f3f3cSopenharmony_ci { 0x0F39, 0x0F39 }, 1025c84f3f3cSopenharmony_ci { 0x0F71, 0x0F7E }, 1026c84f3f3cSopenharmony_ci { 0x0F80, 0x0F84 }, 1027c84f3f3cSopenharmony_ci { 0x0F86, 0x0F87 }, 1028c84f3f3cSopenharmony_ci { 0x0F8D, 0x0F97 }, 1029c84f3f3cSopenharmony_ci { 0x0F99, 0x0FBC }, 1030c84f3f3cSopenharmony_ci { 0x0FC6, 0x0FC6 }, 1031c84f3f3cSopenharmony_ci { 0x102D, 0x1030 }, 1032c84f3f3cSopenharmony_ci { 0x1032, 0x1037 }, 1033c84f3f3cSopenharmony_ci { 0x1039, 0x103A }, 1034c84f3f3cSopenharmony_ci { 0x103D, 0x103E }, 1035c84f3f3cSopenharmony_ci { 0x1058, 0x1059 }, 1036c84f3f3cSopenharmony_ci { 0x105E, 0x1060 }, 1037c84f3f3cSopenharmony_ci { 0x1071, 0x1074 }, 1038c84f3f3cSopenharmony_ci { 0x1082, 0x1082 }, 1039c84f3f3cSopenharmony_ci { 0x1085, 0x1086 }, 1040c84f3f3cSopenharmony_ci { 0x108D, 0x108D }, 1041c84f3f3cSopenharmony_ci { 0x109D, 0x109D }, 1042c84f3f3cSopenharmony_ci { 0x1160, 0x11FF }, 1043c84f3f3cSopenharmony_ci { 0x135D, 0x135F }, 1044c84f3f3cSopenharmony_ci { 0x1712, 0x1714 }, 1045c84f3f3cSopenharmony_ci { 0x1732, 0x1734 }, 1046c84f3f3cSopenharmony_ci { 0x1752, 0x1753 }, 1047c84f3f3cSopenharmony_ci { 0x1772, 0x1773 }, 1048c84f3f3cSopenharmony_ci { 0x17B4, 0x17B5 }, 1049c84f3f3cSopenharmony_ci { 0x17B7, 0x17BD }, 1050c84f3f3cSopenharmony_ci { 0x17C6, 0x17C6 }, 1051c84f3f3cSopenharmony_ci { 0x17C9, 0x17D3 }, 1052c84f3f3cSopenharmony_ci { 0x17DD, 0x17DD }, 1053c84f3f3cSopenharmony_ci { 0x180B, 0x180E }, 1054c84f3f3cSopenharmony_ci { 0x1885, 0x1886 }, 1055c84f3f3cSopenharmony_ci { 0x18A9, 0x18A9 }, 1056c84f3f3cSopenharmony_ci { 0x1920, 0x1922 }, 1057c84f3f3cSopenharmony_ci { 0x1927, 0x1928 }, 1058c84f3f3cSopenharmony_ci { 0x1932, 0x1932 }, 1059c84f3f3cSopenharmony_ci { 0x1939, 0x193B }, 1060c84f3f3cSopenharmony_ci { 0x1A17, 0x1A18 }, 1061c84f3f3cSopenharmony_ci { 0x1A1B, 0x1A1B }, 1062c84f3f3cSopenharmony_ci { 0x1A56, 0x1A56 }, 1063c84f3f3cSopenharmony_ci { 0x1A58, 0x1A5E }, 1064c84f3f3cSopenharmony_ci { 0x1A60, 0x1A60 }, 1065c84f3f3cSopenharmony_ci { 0x1A62, 0x1A62 }, 1066c84f3f3cSopenharmony_ci { 0x1A65, 0x1A6C }, 1067c84f3f3cSopenharmony_ci { 0x1A73, 0x1A7C }, 1068c84f3f3cSopenharmony_ci { 0x1A7F, 0x1A7F }, 1069c84f3f3cSopenharmony_ci { 0x1AB0, 0x1AC0 }, 1070c84f3f3cSopenharmony_ci { 0x1B00, 0x1B03 }, 1071c84f3f3cSopenharmony_ci { 0x1B34, 0x1B34 }, 1072c84f3f3cSopenharmony_ci { 0x1B36, 0x1B3A }, 1073c84f3f3cSopenharmony_ci { 0x1B3C, 0x1B3C }, 1074c84f3f3cSopenharmony_ci { 0x1B42, 0x1B42 }, 1075c84f3f3cSopenharmony_ci { 0x1B6B, 0x1B73 }, 1076c84f3f3cSopenharmony_ci { 0x1B80, 0x1B81 }, 1077c84f3f3cSopenharmony_ci { 0x1BA2, 0x1BA5 }, 1078c84f3f3cSopenharmony_ci { 0x1BA8, 0x1BA9 }, 1079c84f3f3cSopenharmony_ci { 0x1BAB, 0x1BAD }, 1080c84f3f3cSopenharmony_ci { 0x1BE6, 0x1BE6 }, 1081c84f3f3cSopenharmony_ci { 0x1BE8, 0x1BE9 }, 1082c84f3f3cSopenharmony_ci { 0x1BED, 0x1BED }, 1083c84f3f3cSopenharmony_ci { 0x1BEF, 0x1BF1 }, 1084c84f3f3cSopenharmony_ci { 0x1C2C, 0x1C33 }, 1085c84f3f3cSopenharmony_ci { 0x1C36, 0x1C37 }, 1086c84f3f3cSopenharmony_ci { 0x1CD0, 0x1CD2 }, 1087c84f3f3cSopenharmony_ci { 0x1CD4, 0x1CE0 }, 1088c84f3f3cSopenharmony_ci { 0x1CE2, 0x1CE8 }, 1089c84f3f3cSopenharmony_ci { 0x1CED, 0x1CED }, 1090c84f3f3cSopenharmony_ci { 0x1CF4, 0x1CF4 }, 1091c84f3f3cSopenharmony_ci { 0x1CF8, 0x1CF9 }, 1092c84f3f3cSopenharmony_ci { 0x1DC0, 0x1DF9 }, 1093c84f3f3cSopenharmony_ci { 0x1DFB, 0x1DFF }, 1094c84f3f3cSopenharmony_ci { 0x200B, 0x200F }, 1095c84f3f3cSopenharmony_ci { 0x202A, 0x202E }, 1096c84f3f3cSopenharmony_ci { 0x2060, 0x2064 }, 1097c84f3f3cSopenharmony_ci { 0x2066, 0x206F }, 1098c84f3f3cSopenharmony_ci { 0x20D0, 0x20F0 }, 1099c84f3f3cSopenharmony_ci { 0x2CEF, 0x2CF1 }, 1100c84f3f3cSopenharmony_ci { 0x2D7F, 0x2D7F }, 1101c84f3f3cSopenharmony_ci { 0x2DE0, 0x2DFF }, 1102c84f3f3cSopenharmony_ci { 0x302A, 0x302D }, 1103c84f3f3cSopenharmony_ci { 0x3099, 0x309A }, 1104c84f3f3cSopenharmony_ci { 0xA66F, 0xA672 }, 1105c84f3f3cSopenharmony_ci { 0xA674, 0xA67D }, 1106c84f3f3cSopenharmony_ci { 0xA69E, 0xA69F }, 1107c84f3f3cSopenharmony_ci { 0xA6F0, 0xA6F1 }, 1108c84f3f3cSopenharmony_ci { 0xA802, 0xA802 }, 1109c84f3f3cSopenharmony_ci { 0xA806, 0xA806 }, 1110c84f3f3cSopenharmony_ci { 0xA80B, 0xA80B }, 1111c84f3f3cSopenharmony_ci { 0xA825, 0xA826 }, 1112c84f3f3cSopenharmony_ci { 0xA82C, 0xA82C }, 1113c84f3f3cSopenharmony_ci { 0xA8C4, 0xA8C5 }, 1114c84f3f3cSopenharmony_ci { 0xA8E0, 0xA8F1 }, 1115c84f3f3cSopenharmony_ci { 0xA8FF, 0xA8FF }, 1116c84f3f3cSopenharmony_ci { 0xA926, 0xA92D }, 1117c84f3f3cSopenharmony_ci { 0xA947, 0xA951 }, 1118c84f3f3cSopenharmony_ci { 0xA980, 0xA982 }, 1119c84f3f3cSopenharmony_ci { 0xA9B3, 0xA9B3 }, 1120c84f3f3cSopenharmony_ci { 0xA9B6, 0xA9B9 }, 1121c84f3f3cSopenharmony_ci { 0xA9BC, 0xA9BD }, 1122c84f3f3cSopenharmony_ci { 0xA9E5, 0xA9E5 }, 1123c84f3f3cSopenharmony_ci { 0xAA29, 0xAA2E }, 1124c84f3f3cSopenharmony_ci { 0xAA31, 0xAA32 }, 1125c84f3f3cSopenharmony_ci { 0xAA35, 0xAA36 }, 1126c84f3f3cSopenharmony_ci { 0xAA43, 0xAA43 }, 1127c84f3f3cSopenharmony_ci { 0xAA4C, 0xAA4C }, 1128c84f3f3cSopenharmony_ci { 0xAA7C, 0xAA7C }, 1129c84f3f3cSopenharmony_ci { 0xAAB0, 0xAAB0 }, 1130c84f3f3cSopenharmony_ci { 0xAAB2, 0xAAB4 }, 1131c84f3f3cSopenharmony_ci { 0xAAB7, 0xAAB8 }, 1132c84f3f3cSopenharmony_ci { 0xAABE, 0xAABF }, 1133c84f3f3cSopenharmony_ci { 0xAAC1, 0xAAC1 }, 1134c84f3f3cSopenharmony_ci { 0xAAEC, 0xAAED }, 1135c84f3f3cSopenharmony_ci { 0xAAF6, 0xAAF6 }, 1136c84f3f3cSopenharmony_ci { 0xABE5, 0xABE5 }, 1137c84f3f3cSopenharmony_ci { 0xABE8, 0xABE8 }, 1138c84f3f3cSopenharmony_ci { 0xABED, 0xABED }, 1139c84f3f3cSopenharmony_ci { 0xD7B0, 0xD7FF }, 1140c84f3f3cSopenharmony_ci { 0xFB1E, 0xFB1E }, 1141c84f3f3cSopenharmony_ci { 0xFE00, 0xFE0F }, 1142c84f3f3cSopenharmony_ci { 0xFE20, 0xFE2F }, 1143c84f3f3cSopenharmony_ci { 0xFEFF, 0xFEFF }, 1144c84f3f3cSopenharmony_ci { 0xFFF9, 0xFFFB } 1145c84f3f3cSopenharmony_ci}; 1146c84f3f3cSopenharmony_ci 1147c84f3f3cSopenharmony_cistatic const struct mb_ucsrange mb_ucs_fullwidth[] = { 1148c84f3f3cSopenharmony_ci { 0x1100, 0x115F }, 1149c84f3f3cSopenharmony_ci { 0x231A, 0x231B }, 1150c84f3f3cSopenharmony_ci { 0x2329, 0x232A }, 1151c84f3f3cSopenharmony_ci { 0x23E9, 0x23EC }, 1152c84f3f3cSopenharmony_ci { 0x23F0, 0x23F0 }, 1153c84f3f3cSopenharmony_ci { 0x23F3, 0x23F3 }, 1154c84f3f3cSopenharmony_ci { 0x25FD, 0x25FE }, 1155c84f3f3cSopenharmony_ci { 0x2614, 0x2615 }, 1156c84f3f3cSopenharmony_ci { 0x2648, 0x2653 }, 1157c84f3f3cSopenharmony_ci { 0x267F, 0x267F }, 1158c84f3f3cSopenharmony_ci { 0x2693, 0x2693 }, 1159c84f3f3cSopenharmony_ci { 0x26A1, 0x26A1 }, 1160c84f3f3cSopenharmony_ci { 0x26AA, 0x26AB }, 1161c84f3f3cSopenharmony_ci { 0x26BD, 0x26BE }, 1162c84f3f3cSopenharmony_ci { 0x26C4, 0x26C5 }, 1163c84f3f3cSopenharmony_ci { 0x26CE, 0x26CE }, 1164c84f3f3cSopenharmony_ci { 0x26D4, 0x26D4 }, 1165c84f3f3cSopenharmony_ci { 0x26EA, 0x26EA }, 1166c84f3f3cSopenharmony_ci { 0x26F2, 0x26F3 }, 1167c84f3f3cSopenharmony_ci { 0x26F5, 0x26F5 }, 1168c84f3f3cSopenharmony_ci { 0x26FA, 0x26FA }, 1169c84f3f3cSopenharmony_ci { 0x26FD, 0x26FD }, 1170c84f3f3cSopenharmony_ci { 0x2705, 0x2705 }, 1171c84f3f3cSopenharmony_ci { 0x270A, 0x270B }, 1172c84f3f3cSopenharmony_ci { 0x2728, 0x2728 }, 1173c84f3f3cSopenharmony_ci { 0x274C, 0x274C }, 1174c84f3f3cSopenharmony_ci { 0x274E, 0x274E }, 1175c84f3f3cSopenharmony_ci { 0x2753, 0x2755 }, 1176c84f3f3cSopenharmony_ci { 0x2757, 0x2757 }, 1177c84f3f3cSopenharmony_ci { 0x2795, 0x2797 }, 1178c84f3f3cSopenharmony_ci { 0x27B0, 0x27B0 }, 1179c84f3f3cSopenharmony_ci { 0x27BF, 0x27BF }, 1180c84f3f3cSopenharmony_ci { 0x2B1B, 0x2B1C }, 1181c84f3f3cSopenharmony_ci { 0x2B50, 0x2B50 }, 1182c84f3f3cSopenharmony_ci { 0x2B55, 0x2B55 }, 1183c84f3f3cSopenharmony_ci { 0x2E80, 0x3029 }, 1184c84f3f3cSopenharmony_ci { 0x302E, 0x303E }, 1185c84f3f3cSopenharmony_ci { 0x3040, 0x3098 }, 1186c84f3f3cSopenharmony_ci { 0x309B, 0xA4CF }, 1187c84f3f3cSopenharmony_ci { 0xA960, 0xA97F }, 1188c84f3f3cSopenharmony_ci { 0xAC00, 0xD7A3 }, 1189c84f3f3cSopenharmony_ci { 0xF900, 0xFAFF }, 1190c84f3f3cSopenharmony_ci { 0xFE10, 0xFE19 }, 1191c84f3f3cSopenharmony_ci { 0xFE30, 0xFE6F }, 1192c84f3f3cSopenharmony_ci { 0xFF01, 0xFF60 }, 1193c84f3f3cSopenharmony_ci { 0xFFE0, 0xFFE6 } 1194c84f3f3cSopenharmony_ci}; 1195c84f3f3cSopenharmony_ci 1196c84f3f3cSopenharmony_ci/* simple binary search in ranges, with bounds optimisation */ 1197c84f3f3cSopenharmony_cistatic int 1198c84f3f3cSopenharmony_cimb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems, unsigned int val) 1199c84f3f3cSopenharmony_ci{ 1200c84f3f3cSopenharmony_ci size_t min = 0, mid, max = elems; 1201c84f3f3cSopenharmony_ci 1202c84f3f3cSopenharmony_ci if (val < arr[min].beg || val > arr[max - 1].end) 1203c84f3f3cSopenharmony_ci return (0); 1204c84f3f3cSopenharmony_ci 1205c84f3f3cSopenharmony_ci while (min < max) { 1206c84f3f3cSopenharmony_ci mid = (min + max) / 2; 1207c84f3f3cSopenharmony_ci 1208c84f3f3cSopenharmony_ci if (val < arr[mid].beg) 1209c84f3f3cSopenharmony_ci max = mid; 1210c84f3f3cSopenharmony_ci else if (val > arr[mid].end) 1211c84f3f3cSopenharmony_ci min = mid + 1; 1212c84f3f3cSopenharmony_ci else 1213c84f3f3cSopenharmony_ci return (1); 1214c84f3f3cSopenharmony_ci } 1215c84f3f3cSopenharmony_ci return (0); 1216c84f3f3cSopenharmony_ci} 1217c84f3f3cSopenharmony_ci 1218c84f3f3cSopenharmony_ci/* Unix column width of a wide character (UCS code point, really) */ 1219c84f3f3cSopenharmony_ciint 1220c84f3f3cSopenharmony_ciutf_wcwidth(unsigned int wc) 1221c84f3f3cSopenharmony_ci{ 1222c84f3f3cSopenharmony_ci /* except NUL, C0/C1 control characters and DEL yield -1 */ 1223c84f3f3cSopenharmony_ci if (wc < 0x20 || (wc >= 0x7F && wc < 0xA0)) 1224c84f3f3cSopenharmony_ci return (wc ? -1 : 0); 1225c84f3f3cSopenharmony_ci 1226c84f3f3cSopenharmony_ci /* combining characters use 0 screen columns */ 1227c84f3f3cSopenharmony_ci if (mb_ucsbsearch(mb_ucs_combining, NELEM(mb_ucs_combining), wc)) 1228c84f3f3cSopenharmony_ci return (0); 1229c84f3f3cSopenharmony_ci 1230c84f3f3cSopenharmony_ci /* all others use 1 or 2 screen columns */ 1231c84f3f3cSopenharmony_ci if (mb_ucsbsearch(mb_ucs_fullwidth, NELEM(mb_ucs_fullwidth), wc)) 1232c84f3f3cSopenharmony_ci return (2); 1233c84f3f3cSopenharmony_ci return (1); 1234c84f3f3cSopenharmony_ci} 1235c84f3f3cSopenharmony_ci#endif 1236