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