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