1/* expr.c */
2/*****************************************************************************
3					�s�������@�o�����������������@�w�s�q
4
5							�m���̕]���n
6*****************************************************************************/
7
8#include "xtr.h"
9
10/***************************************************************************
11
12<fstring> : { <%-form> | <char> }*
13
14<%-form>     : '%' [<%-form2>]
15
16<%-form2>    : <env-var> '%'
17             | ['-'] <arg-#>
18             | ['-'] [<f-width>] {<func> | <func-call>}
19             | ':' <format> <expr-prim-f>
20             | <expr-prim-f>
21             | <\-sequence>
22             | '%'
23             | '<'
24             | '>'
25
26<format>     : {<f-flag>}* [<f-width>] ['.' <f-prec>] <f-type>
27
28<f-flag>     : ' ' | '+' | '-' | '#'
29<f-width>    : <num>
30<f-prec>     : <num>
31<f-type>     : <null>
32             | 's' | 'd' | 'u' | 'o' | 'x' | 'X' | 'c' | 'O' | 'k'
33             | 'S' | 'C' | 'r' | 'R' | 'a' | 'A' | 'f' | 'e' | 'E'
34             | 'g' | 'G'
35
36<func-call>   : <func> { <func-args> | <expr-prim-f> }
37
38<func-args>   : '(' [ <expr-asgn> { ',' <expr-asgn> }* ] ')'
39
40<env-var>     : <name>
41
42<func>        : <name>
43
44<num>         : <digits>
45
46<name>    : {<alpha> | '_'} {<alpha> | '_' | <digit>}*
47
48<arg-#>   : <num>
49
50<expr>    : <expr-asgn> {',' <expr-asgn>}*
51
52<expr-asgn> : <var>
53              {'=' | '*=' | '/=' | '%=' | '+=' | '-='
54                   | '&=' | '^=' | '|=' | '<<=' | '>>=' | '**='}
55              <expr-asgn>
56            | <expr-cond>
57
58<expr-cond> : <expr-lor> ['?' <expr> ':' <expr-cond>}]
59<expr-lor>  : <expr-land> {'||' <expr-land>}*
60<expr-land> : <expr-or> {'&&' <expr-or>}*
61<expr-or>   : <expr-xor> {'|' <expr-xor>}*
62<expr-xor>  : <expr-and> {'^' <expr-and>}*
63<expr-and>  : <expr-rel> {'&' <expr-rel>}*
64<expr-rel>  : <expr-conc> {{'==' | '!=' | '<' | '<=' | '>' | '>='}<expr-conc>}*
65<expr-conc> : <expr-sh> {<expr-sh>}*
66<expr-sh>   : <expr-add> {{'<<' | '>>'} <expr-add>}*
67<expr-add>  : <expr-mul> {{'+' | '-'} <expr-mul>}*
68<expr-mul>  : <expr-pref> {{'*' | '/' | '%'} <expr-pref>}*
69<expr-pref> : {'!' | '~' | '-' | '+'} <expr-pref> | <expr-pow>
70<expr-pow>  : <expr-inc> {'**' <expr-inc>}*
71<expr-inc>  : {'++' | '--'} <expr-prim> | <expr-prim> [ '++' | '--']
72
73<expr-prim>  : <expr-prim-f>
74             | <func-call>
75             | <var>
76             | <number>
77
78<expr-prim-f> : '(' <expr> ')'
79              | '[' <expr> ']'
80              | '{' <fstring> '}'
81              | '"' <qstring> '"'
82              | "'" <echar> "'"
83              | '`' <expr-prim>
84              | '@' <expr-prim>
85
86<number>  : <digits>
87          | '0x' <hexdigits>
88          | '0o' <octdigits>
89          | '0b' <bindigits>
90
91<var>     : <usr-var> | <sys-var>
92
93<usr-var> : <name>
94<sys-var> : '.' <name>
95
96<qstring> : { <echar> }*
97
98<echar>   : { <char> | <\-sequence> }
99
100<\-sequence> : '\' <\-sequence2>
101
102<\-sequence2> : 'a'
103              | 'b'
104              | 'f'
105              | 'n'
106              | 'r'
107              | 't'
108              | 'v'
109              | 'e'
110              | 'c'
111              | 's'
112              | 'S'
113              | 'z'
114              | 'x' <hexdigits>
115              | 'o' <octdigits>
116              | ['d'] <digits>
117              | <char>
118
119***************************************************************************/
120
121#define EXPR1_PREFS			"-!~+."
122#define EXPR0_PREFS			"({\"'@`["
123
124/* ������ p �� <expr> �ł��邩���ׂ� */
125#define IsExpr(p)		(*(p) && (IsKSym2Str(p) || \
126							strchr(EXPR0_PREFS, *(p)) || \
127							strchr(EXPR1_PREFS, *(p)) && *(p+1) != '='))
128
129/* ������ p �� <expr-prim-f> �ł��邩���ׂ� */
130#define IsExprPrimF(p)	(*(p) && strchr(EXPR0_PREFS, *(p)))
131
132int
133IsFuncArgStr(const uchar *p)
134{
135	return IsExprPrimF(p);
136}
137
138/******************************** EvalExpr ********************************/
139
140#if UNIX
141#define ERROR_SE(fmt,s,e)												\
142	do {																\
143		uchar *_str, *_mbs;												\
144		int _len;														\
145		_len = (int)((e) - (s));										\
146		_str = (uchar *)alloca(_len + 1);								\
147		memcpy((char *)_str, (char *)(s), _len);						\
148		_str[_len] = '\0';												\
149		_mbs = (uchar *)alloca(_len * 2 + 1);							\
150		sjis2mbstring((char *)_mbs, (char *)_str);						\
151		Error((fmt), _mbs);												\
152	} while (0)
153#define ExprErr(s, e)		ERROR_SE("Invalid expression: %s", s, e)
154#else
155#define ExprErr(s, e)		Error(f_ExprErr, (int)((e)-(s)), (s))
156static uchar f_ExprErr[] = "Invalid expression: %.*s";
157#endif
158
159#if UNIX
160#define DivZeroErr(s, e)	ERROR_SE("Can't divide by 0: %s", s, e)
161#else
162#define DivZeroErr(s, e)	Error(f_DivZeroErr, (int)((e)-(s)), (s))
163static uchar f_DivZeroErr[] = "Can't divide by 0: %.*s";
164#endif
165
166#if UNIX
167#define AsgnErr(s, e)		ERROR_SE("Illegal assignment: %s", s, e)
168#else
169#define AsgnErr(s, e)		Error(f_AsgnErr, (int)((e)-(s)), (s))
170static uchar f_AsgnErr[] = "Illegal assignment: %.*s";
171#endif
172
173static int	unclosedflag;	/* ���ʗނ��‚��Ă��Ȃ����Ƃ������t���O */
174
175static const uchar *srcp;
176static const uchar *expr;
177static uchar *valstr;
178static int   vallen;
179static exprval_t exprval;
180
181static int
182ValNumStr(exprval_t val)
183{
184	if (nevflag) return 0;
185
186	return vallen = WtNumber(valstr, val);
187}
188
189static int
190ValNum(exprval_t val)
191{
192	if (nevflag) return 0;
193
194	if (val == 0) {
195		return vallen = WtNum(valstr, 0);
196	} else {
197		*valstr = 0;
198		return vallen = 0;
199	}
200}
201
202static int
203ValStr(exprval_t val)
204{
205	if (nevflag) return 0;
206
207	if (val == 0 || vallen)
208		return vallen;
209	else
210		return vallen = WtNumber(valstr, val);
211}
212
213static exprval_t
214ValVal(exprval_t val)
215{
216	if (nevflag) return 0;
217
218	if (val == 0)
219		return RdNumber(valstr, (const uchar **)NULL);
220	else
221		return val;
222}
223
224static exprval_t Expr ARGS((void));
225static exprval_t Expr_asgn ARGS((void));
226static exprval_t Expr_cond ARGS((void));
227static exprval_t Expr_lor ARGS((void));
228static exprval_t Expr_land ARGS((void));
229static exprval_t Expr_or ARGS((void));
230static exprval_t Expr_xor ARGS((void));
231static exprval_t Expr_and ARGS((void));
232static exprval_t Expr_rel ARGS((void));
233static exprval_t Expr_conc ARGS((void));
234static exprval_t Expr_sh ARGS((void));
235static exprval_t Expr_add ARGS((void));
236static exprval_t Expr_mul ARGS((void));
237static exprval_t Expr_pref ARGS((void));
238static exprval_t Expr_pow ARGS((void));
239static exprval_t Expr_inc ARGS((void));
240static exprval_t Expr_prim ARGS((void));
241
242
243int
244EvalExpr(uchar *dst, const uchar *src, const uchar **endp, evlev_t evlevel)
245/* ����]������B
246 * evlevel �łǂ��܂Ŏ���ǂނ����w��
247 */
248{
249	int len;
250	const uchar *srcp0 = srcp;
251	const uchar *expr0 = expr;
252	uchar *valstr0 = valstr;
253	int   vallen0 = vallen;
254	int   nevflag0 = nevflag;
255
256	assert(nevflag || dst != NULL);
257	assert(src != NULL);
258
259	expr = srcp = SkipSpace(src);
260	if (!nevflag)
261		*dst = '\0';
262
263	valstr = dst;
264	vallen = 0;
265
266	exprval = 0;
267
268	if (IsExpr(srcp)) {
269		switch (evlevel) {
270		case EXPR_MAX:
271			exprval = Expr();
272			break;
273		case EXPR_SEMIMAX:
274			exprval = Expr_asgn();
275			break;
276		case EXPR_MIN:
277		case EXPR_PRIM:
278			exprval = Expr_prim();
279			break;
280		default:
281			assert(FALSE);
282		}
283	}
284
285	len = ValStr(exprval);
286	if (endp)
287		*endp = BackSkipSpace(src, srcp);
288	else if (*CutSpace(srcp) != '\0' && *srcp != ';' && !noerrmode )
289		ExprErr(src, SkipMoji(srcp));
290
291	srcp = srcp0;
292	expr = expr0;
293	valstr = valstr0;
294	vallen = vallen0;
295	nevflag = nevflag0;
296	return len;
297}
298
299/**************************************/
300
301static
302exprval_t Expr(void)
303/*
304 *  <expr>    : <expr-asgn> {',' <expr-asgn>}*
305 */
306{
307	exprval_t val = Expr_asgn();
308
309	while (*CutSpace(srcp) == ',') {
310		srcp++;
311		val = Expr_asgn();
312	}
313	return val;
314}
315
316#if UNIX
317#define UnkSysVarErr(s)													\
318	do {																\
319		uchar *_mbs = (uchar *)alloca(strlen((char *)(s)) * 2);			\
320		sjis2mbstring((char *)_mbs, (char *)(s));						\
321		Error("Unknown system variable: %s", _mbs);						\
322	} while (0)
323#else
324#define UnkSysVarErr(s)		Error(f_UnkSysVar, s)
325static uchar f_UnkSysVar[] = "Unknown system variable: %s";
326#endif
327
328static void
329PutVar1(const uchar *name, int nlen, const uchar *s, int len)
330{
331	uchar nbuf[128];
332
333	CopyStrN(nbuf, name, min(nlen, 127));
334	if (*nbuf == '.') {
335		exprval_t val = RdNumber(s, (const uchar **)NULL);
336		void *varptr;
337		unsigned vartyp = GetSysVar(&varptr, nbuf+1);
338		if (vartyp == V_UNKNOWN) {
339			if (!noerrmode)
340				UnkSysVarErr(nbuf);
341		} else if (vartyp & V_RONLY) {
342			if (!noerrmode)
343				AsgnErr(name, name+nlen);
344		} else switch (vartyp) {
345		case V_INT:
346			*(int *)varptr = (int)val;
347			break;
348		case V_UINT:
349			*(unsigned *)varptr = (unsigned)val;
350			break;
351		default:
352			assert(FALSE);
353		}
354	} else {
355		PutVar(nbuf, s, len);
356	}
357}
358
359static uchar *
360GetVar1(const uchar *name, int nlen, int *lenp, exprval_t *valp)
361{
362	uchar nbuf[128];
363
364	assert(name != NULL);
365
366	CopyStrN(nbuf, name, min(nlen, 127));
367	if (*nbuf == '.') {
368		void *varptr;
369		unsigned vartyp = GetSysVar(&varptr, nbuf+1);
370
371		assert(valp != NULL);
372
373		if (vartyp == V_UNKNOWN) {
374			if (!noerrmode)
375				UnkSysVarErr(nbuf);
376		} else switch (vartyp & ~V_RONLY) {
377		case V_INT:
378			*valp = (exprval_t)(*(int *)varptr);
379			break;
380		case V_UINT:
381			*valp = (exprval_t)(*(unsigned *)varptr);
382			break;
383		default:
384			assert(FALSE);
385		}
386		if (lenp) *lenp = 0;
387		return NULL;
388	} else {
389		uchar *p = GetVar(nbuf, lenp);
390		if (valp != NULL)
391			*valp = RdNumber(p, (const uchar **)NULL);
392		return p;
393	}
394}
395
396#ifdef FLOATEXPR
397 #define Add(a, b)		FAdd(a, b)
398 #define Sub(a, b)		FAdd(a, -(b))
399
400/* ���������_���̉����Z�ŁA���ʂ̒l������������Ƃ� 0 �ɂȂ�悤�ɂ��� */
401
402static exprval_t
403FAdd(exprval_t a, exprval_t b)
404{
405	exprval_t c = a + b;
406	if (Abs(c) > Abs(a) * _Paste2(10e-, DBL_DIG))
407		return c;
408	else {
409		uchar buf[32];
410		WtNumber(buf, a);
411		a = RdNumber(buf, (const uchar **)NULL);
412		WtNumber(buf, b);
413		if (a + RdNumber(buf, (const uchar **)NULL) == 0)
414			return 0;
415		else
416			return c;
417	}
418}
419
420#else
421 #define Add(a, b)		((a) + (b))
422 #define Sub(a, b)		((a) - (b))
423#endif
424
425
426static exprval_t Ex_sh ARGS((exprval_t a, exprval_t b, int rflag));
427static exprval_t Ex_pow ARGS((exprval_t a, exprval_t b));
428
429#define IsAsgnOp(p)		(*((p)+1) != '=' ? \
430							*(p) == '=' || \
431							 *((p)+2) == '=' && \
432							  (*(p) == '<' || *(p) == '>' || *(p) == '*') && \
433							  *(p) == *((p)+1) : \
434						    *(p) && strchr("*%/+-&^|", *(p)))
435
436#define SkipAsgnOp(p)	((p) + (*(p) == '=' ? 1 : *((p)+1) == '=' ? 2 : 3))
437
438#define IsVarStr(p)		(*(p) == '.' ? IsSym1_(*((p)+1)) : IsKSym1Str(p))
439#define SkipVar(p)		(*(p) == '.' ? SkipSym2((p)+1) : SkipKSym2(p))
440
441static exprval_t
442Expr_asgn(void)
443/*
444 *  <expr-asgn> : <var>
445 *                {'=' | '*=' | '/=' | '%=' | '+=' | '-='
446 *                     | '&=' | '^=' | '|=' | '<<=' | '>>=' || '**='}
447 *                <expr-asgn>
448 *              | <expr-cond>
449 */
450{
451	const uchar *sp0 = CutSpace(srcp);
452	const uchar *sp1;
453	int  op;
454	exprval_t  val;
455	exprval_t  val2;
456
457	if (!IsVarStr(srcp)) {
458		val = Expr_cond();
459		CutSpace(srcp);
460		if (IsAsgnOp(srcp) && (srcp = SkipAsgnOp(srcp), !noerrmode))
461			AsgnErr(sp0, srcp);
462		return val;
463	}
464	sp1 = SkipVar(srcp);
465	srcp = SkipSpace(sp1);
466	if (!IsAsgnOp(srcp)) {
467		srcp = sp0;
468		val = Expr_cond();
469		CutSpace(srcp);
470		if (IsAsgnOp(srcp) && (srcp = SkipAsgnOp(srcp), !noerrmode))
471			AsgnErr(sp0, srcp);
472		return val;
473	}
474	op = *srcp;
475	if (op == '*' && *(srcp+1) == '*') op = 'P';
476	srcp = SkipAsgnOp(srcp);
477
478	if (nevflag)
479		return Expr_asgn();
480
481	if (op == '=') {
482		val = Expr_asgn();
483		ValStr(val);
484		PutVar1(sp0, sp1-sp0, valstr, vallen);
485	} else {
486		GetVar1(sp0, sp1-sp0, (int *)NULL, &val);
487		val2 = Expr_asgn();
488		if (val2 == 0 && (op == '/' || op == '%')) {
489			if (!noerrmode)
490				DivZeroErr(sp0, srcp);
491			else
492				val2 = 1;
493		}
494		switch (op) {
495		case '*':
496			val *= val2;
497			break;
498		case '/':
499			val /= val2;
500			break;
501		case '%':
502#ifdef FLOATEXPR
503			val = fmod(val, val2);
504#else
505			val %= val2;
506#endif
507			break;
508		case '+':
509			val = Add(val, val2);
510			break;
511		case '-':
512			val = Sub(val, val2);
513			break;
514		case '&':
515			val = (exprintval_t)val & (exprintval_t)val2;
516			break;
517		case '^':
518			val = (exprintval_t)val ^ (exprintval_t)val2;
519			break;
520		case '|':
521			val = (exprintval_t)val | (exprintval_t)val2;
522			break;
523		case '<':						/* <<= */
524			val = Ex_sh(val, val2, 0);
525			break;
526		case '>':						/* >>= */
527			val = Ex_sh(val, val2, 1);
528			break;
529		case 'P':						/* **= */
530			val = Ex_pow(val, val2);
531			break;
532		default:
533			assert(FALSE);				/* Never */
534		}
535		ValNumStr(val);
536		PutVar1(sp0, sp1-sp0, valstr, vallen);
537	}
538	return val;
539}
540
541static exprval_t
542Expr_cond(void)
543/*
544 *  <expr-cond>  : <expr-lor> ['?' <expr> ':' <expr-cond>}]
545 */
546{
547	const uchar *sp0 = srcp;
548	exprval_t val_c = Expr_lor();
549	exprval_t val_th;
550	exprval_t val_el;
551	int nevflag0 = nevflag;
552
553	if (*CutSpace(srcp) != '?')
554		return val_c;
555
556	srcp++;
557	if (!val_c) nevflag = TRUE;
558	val_th = Expr();
559	if (*CutSpace(srcp) != ':') {
560		if (!noerrmode)
561			ExprErr(sp0, SkipMoji(srcp));
562		else
563			--srcp;
564	}
565	srcp++;
566	nevflag = nevflag0;
567	if (val_c) nevflag = TRUE;
568	val_el = Expr_cond();
569	nevflag = nevflag0;
570	if (val_c)
571		return val_th;
572	else
573		return val_el;
574}
575
576static exprval_t
577Expr_lor(void)
578/*
579 *  <expr-lor> : <expr-land> {'||' <expr-land>}*
580 */
581{
582	exprval_t val = Expr_land();
583	int nevflag0 = nevflag;
584
585	while (*CutSpace(srcp) == '|' && *(srcp+1) == '|') {
586		srcp += 2;
587		if (val) {
588			nevflag = TRUE;
589			Expr_land();
590		} else {
591			val = Expr_land();
592		}
593	}
594	nevflag = nevflag0;
595	return val;
596}
597
598static exprval_t
599Expr_land(void)
600/*
601 *  <expr-land> : <expr-or> {'&&' <expr-or>}*
602 */
603{
604	exprval_t val = Expr_or();
605	int nevflag0 = nevflag;
606
607	while (*CutSpace(srcp) == '&' && *(srcp+1) == '&') {
608		srcp += 2;
609		if (val) {
610			val = Expr_or();
611		} else {
612			nevflag = TRUE;
613			Expr_or();
614		}
615	}
616	nevflag = nevflag0;
617	return val;
618}
619
620static exprval_t
621Expr_or(void)
622/*
623 *  <expr-or>  : <expr-xor> {'|' <expr-xor>}*
624 */
625{
626	exprval_t val = Expr_xor();
627	while (*CutSpace(srcp) == '|' && *(srcp+1) != '|' && *(srcp+1) != '=') {
628		srcp++;
629		if (!nevflag)
630			val = (exprintval_t)val | (exprintval_t)Expr_xor();
631		else
632			(void)Expr_xor();
633		ValNum(val);
634	}
635	return val;
636}
637
638static exprval_t
639Expr_xor(void)
640/*
641 *  <expr-xor> : <expr-and> {'^' <expr-and>}*
642 */
643{
644	exprval_t val = Expr_and();
645	while (*CutSpace(srcp) == '^' && *(srcp+1) != '=') {
646		srcp++;
647		if (!nevflag)
648			val = (exprintval_t)val ^ (exprintval_t)Expr_and();
649		else
650			(void)Expr_and();
651		ValNum(val);
652	}
653	return val;
654}
655
656static exprval_t
657Expr_and(void)
658/*
659 *  <expr-and>  : <expr-rel> {'&' <expr-rel>}*
660 */
661{
662	exprval_t val = Expr_rel();
663	while (*CutSpace(srcp) == '&' && *(srcp+1) != '&' && *(srcp+1) != '=') {
664		srcp++;
665		if (!nevflag)
666			val = (exprintval_t)val & (exprintval_t)Expr_rel();
667		else
668			(void)Expr_rel();
669		ValNum(val);
670	}
671	return val;
672}
673
674static exprval_t
675Expr_rel(void)
676/*
677 *  <expr-rel>  : <expr-conc> {{'==' | '!=' | '<' | '<=' | '>' | '>='}
678 *                             <expr-conc>}*
679 */
680{
681	exprval_t val = Expr_conc();
682	exprval_t val2;
683	uchar *valstr0 = valstr;
684	int  op;
685	int  vallen0 = vallen;
686
687	while (1) {
688		if ((op = *CutSpace(srcp)) == '=' ? *(srcp+1) == '=' :
689		                  *srcp == '!' && *(srcp+1) == '=' ) {
690			srcp += 2;
691			ValStr(val);
692			if (!nevflag)
693				valstr += vallen + 1;
694			vallen0 = vallen;
695			val2 = Expr_conc();
696			val = ((Sub(val, val2) == 0) && (vallen0 == ValStr(val2)) &&
697						!memcmp(valstr0, valstr, vallen));
698						/* �������������܂߂Ċ��S�Ɉ�v����ꍇ�̂ݐ^ */
699			if (op == '!')
700				val = !val;
701			valstr = valstr0;
702			ValNum(val);
703		} else if (*srcp == '<' && *(srcp+1) == '=') {
704			srcp += 2;
705			val = Sub(val, Expr_conc()) <= 0;
706			ValNum(val);
707		} else if (*srcp == '<' && *(srcp+1) != '<') {
708			srcp++;
709			val = Sub(val, Expr_conc()) < 0;
710			ValNum(val);
711		} else if (*srcp == '>' && *(srcp+1) == '=') {
712			srcp += 2;
713			val = Sub(val, Expr_conc()) >= 0;
714			ValNum(val);
715		} else if (*srcp == '>' && *(srcp+1) != '>') {
716			srcp++;
717			val = Sub(val, Expr_conc()) > 0;
718			ValNum(val);
719		} else
720			break;
721	}
722	return val;
723}
724
725
726static exprval_t
727Expr_conc(void)
728/*
729 *  <expr-conc> : <expr-sh> {<expr-sh>}*
730 */
731{
732	uchar *valstr0 = valstr;
733	exprval_t val = Expr_sh();
734
735	CutSpace(srcp);
736	if (IsExpr(srcp)) {
737		do {
738			valstr += ValStr(val);
739			val = Expr_sh();
740			CutSpace(srcp);
741		} while (IsExpr(srcp));
742
743		if (!nevflag) {
744			ValStr(val);
745			vallen += valstr - valstr0;
746		}
747		valstr = valstr0;
748		val = ValVal(0);
749	}
750	return val;
751}
752
753static exprval_t
754Ex_sh(exprval_t a, exprval_t b, int rflag)
755{
756	if (b < 0) {
757		rflag = !rflag;
758		b = -b;
759	}
760	if (rflag)
761		return (exprval_t)(exprintval_t)((unsigned long)a >> (exprintval_t)b);
762	else
763		return (exprval_t)(exprintval_t)((unsigned long)a << (exprintval_t)b);
764}
765
766static exprval_t
767Expr_sh(void)
768/*
769 *  <expr-sh>  : <expr-add> {{'<<' | '>>'} <expr-add>}*
770 */
771{
772	exprval_t val = Expr_add();
773	while (*CutSpace(srcp) == '<' && *(srcp+1) == '<' && *(srcp+2) != '=' ||
774		             *srcp == '>' && *(srcp+1) == '>' && *(srcp+2) != '=') {
775		int rflag = *srcp == '>';
776		srcp += 2;
777		val = Ex_sh(val, Expr_add(), rflag);
778		ValNum(val);
779	}
780	return val;
781}
782
783static exprval_t
784Expr_add(void)
785/*
786 *  <expr-add>  : <expr-mul> {{'+' | '-'} <expr-mul>}*
787 */
788{
789	exprval_t val = Expr_mul();
790	while (1)
791		if (*CutSpace(srcp) == '+' && *(srcp+1) != '+' && *(srcp+1) != '=') {
792			srcp++;
793			val = Add(val, Expr_mul());
794			ValNum(val);
795		} else if (*srcp == '-' && *(srcp+1) != '-' && *(srcp+1) != '=') {
796			srcp++;
797			val = Sub(val, Expr_mul());
798			ValNum(val);
799		} else
800			break;
801	return val;
802}
803
804static exprval_t
805Expr_mul(void)
806/*
807 *  <expr-mul>  : <expr-pref> {{'*' | '/' | '%'} <expr-pref>}*
808 */
809{
810	const uchar *sp0 = CutSpace(srcp);
811	exprval_t val = Expr_pref();
812	exprval_t val2;
813	int op;
814
815	while (((op = *(CutSpace(srcp))) == '*' || op == '/' || op == '%') &&
816			*(srcp+1) != '*' && *(srcp+1) != '=') {
817		srcp++;
818		val2 = Expr_pref();
819		if (!nevflag) {
820			if (val2 == 0 && op != '*') {
821				if (!noerrmode)
822					DivZeroErr(sp0, srcp);
823				else
824					val2 = 1;
825			}
826			switch (op) {
827			case '*':
828				val *= val2;
829				break;
830			case '/':
831				val /= val2;
832				break;
833			case '%':
834#ifdef FLOATEXPR
835				val = fmod(val, val2);
836#else
837				val %= val2;
838#endif
839				break;
840			default:
841				assert(FALSE);
842			}
843		}
844		ValNum(val);
845	}
846	return val;
847}
848
849
850static exprval_t
851Expr_pref(void)
852/*
853 *  <expr-pref>  : {'!' | '~' | '-' | '+'} <expr-pref>
854 *               | <expr-pow>
855 */
856{
857	exprval_t val;
858
859	if (*CutSpace(srcp) == '!' && *(srcp+1) != '=') {
860		srcp++;
861		val = !Expr_pref();
862	} else if (*srcp == '~') {
863		srcp++;
864		val = ~(exprintval_t)Expr_pref();
865	} else if (*srcp == '-' && *(srcp+1) != '-' && *(srcp+1) != '=') {
866		srcp++;
867		val = -Expr_pref();
868	} else if (*srcp == '+' && *(srcp+1) != '+' && *(srcp+1) != '=') {
869		srcp++;
870		val = +Expr_pref();
871	} else
872		return Expr_pow();
873
874	ValNum(val);
875	return val;
876}
877
878static exprval_t
879Ex_pow(exprval_t a, exprval_t b)
880{
881	if (nevflag) return 0;
882
883	if (b == 0 || a == 1)
884		return 1;
885	else if (a == 0)
886		return 0;
887
888#ifdef FLOATEXPR
889	return pow(a, b);
890
891#else
892	if (a == -1)
893		return b & 1 ? -1 : 1;
894	else if (b < 0)
895		return 0;
896	else if (b >= 64)	/* too big !! */
897		return 0;
898	else {
899		exprval_t val = a;
900		while (--b > 0)
901			val *= a;
902		return val;
903	}
904#endif
905}
906
907static exprval_t
908Expr_pow(void)
909/*
910 *  <expr-pow> : <expr-inc> {'**' <expr-inc>}*
911 */
912{
913	exprval_t val = Expr_inc();
914	while (*CutSpace(srcp) == '*' && *(srcp+1) == '*' && *(srcp+2) != '=') {
915		srcp += 2;
916		val = Ex_pow(val, Expr_inc());
917		ValNum(val);
918	}
919	return val;
920}
921
922
923#define IsIncDecOp(s)  ((*(s) == '+' || *(s) == '-') && *(s) == *((s)+1))
924
925static exprval_t
926Expr_inc(void)
927/*
928 *  <expr-inc>  : {'++' | '--'} <expr-prim>
929 *              | <expr-prim> [ '++' | '--']
930 */
931{
932	const uchar *sp0 = CutSpace(srcp);
933	const uchar *sp1;
934	exprval_t val;
935
936	if (IsIncDecOp(srcp)) {
937		srcp += 2;
938		sp1 = CutSpace(srcp);
939		val = Expr_prim();
940		if (!IsVarStr(sp1)) {
941			if (!noerrmode)
942				AsgnErr(sp0, srcp);
943		} else if (!nevflag) {
944			if (*sp0 == '+')
945				++val;
946			else
947				--val;
948			ValNumStr(val);
949			PutVar1(sp1, srcp-sp1, valstr, vallen);
950		}
951	} else {
952		val = Expr_prim();
953		sp1 = srcp;
954		CutSpace(srcp);
955		if (!IsIncDecOp(srcp))
956			return val;
957
958		if (!IsVarStr(sp0)) {
959			if (!noerrmode)
960				AsgnErr(sp0, srcp+2);
961		} else if (!nevflag) {
962			ValNumStr(*srcp == '+' ? val + 1 : val - 1);
963			PutVar1(sp0, sp1-sp0, valstr, vallen);
964		}
965		srcp += 2;
966	}
967	ValNum(val);
968	return val;
969}
970
971static int FuncCall ARGS((uchar *dst, const uchar *name, const uchar *src, const uchar **endp, exprval_t *fretvalp));
972
973static exprval_t
974Expr_prim(void)
975/*
976 *  <expr-prim>  : '(' <expr> ')'
977 *               | '[' <expr> ']'
978 *               | '{' <fstring> '}'
979 *               | '"' <qstring> '"'
980 *               | "'" <echar> "'"
981 *               | '`' <expr-prim>
982 *               | '@' <expr-prim>
983 *               | <func-call>
984 *               | <sys-var>
985 *               | <usr-var>
986 *               | <number>
987 */
988{
989	uchar *dst = valstr;
990	uchar *dstp = dst;
991	const uchar *sp0;
992	const uchar *p;
993	exprval_t  val = 0;
994
995	assert(nevflag || dstp != NULL);
996	assert(srcp != NULL);
997
998	unclosedflag = FALSE;			/* ���ʗނ��‚������̃`�F�b�N�p */
999
1000	while (*CutSpace(srcp) == '@')						/* '@' <expr-prim> */
1001		srcp++;
1002
1003	sp0 = srcp;
1004
1005	if (!nevflag) {
1006		*dstp = '\0';
1007		vallen = 0;
1008		val = 0;
1009	}
1010
1011	if (*srcp == '(' || *srcp == '[') {					/* '(' <expr> ')' */
1012														/* '[' <expr> ']' */
1013		srcp = SkipSpace(srcp+1);
1014		if (*srcp != ')' && *srcp != ']')
1015			val = Expr();
1016		if (*CutSpace(srcp) == (*sp0 == '(' ? ')' : ']')) {
1017			srcp++;
1018			unclosedflag = FALSE;
1019		} else {
1020			if (!noerrmode)
1021#if UNIX
1022			{
1023				uchar *str, *mbs;
1024				int len;
1025
1026				len = (int)(srcp - sp0);
1027				str = (uchar *)alloca(len + 1);
1028				memcpy((char *)str, (char *)sp0, len);
1029				str[len] = '\0';
1030				mbs = (uchar *)alloca(len * 2 + 1);
1031				sjis2mbstring((char *)mbs, (char *)str);
1032				Error("'%c' expected: %s", (*sp0 == '(' ? ')' : ']'), mbs);
1033			}
1034#else
1035				Error("'%c' expected: %.*s",
1036								(*sp0 == '(' ? ')' : ']'),
1037								(int)(srcp-sp0), sp0);
1038#endif
1039			while (*srcp && *srcp != ')' && *srcp != ']') {
1040				if (!IsExpr(srcp))
1041					srcp = SkipMoji(srcp);
1042				val = Expr();
1043			}
1044			if (*srcp) {
1045				srcp++;
1046				unclosedflag = FALSE;
1047			} else {
1048				unclosedflag = TRUE;
1049			}
1050		}
1051	} else if (*srcp == '{') {							/* '{' <fstring> '}' */
1052		dstp += EvalStringB(dstp, srcp+1, &srcp, 1);
1053		valstr = dst;
1054		if (!nevflag) {
1055			vallen = dstp - dst;
1056			val = ValVal(0);
1057		}
1058	} else if (*srcp == '"') {							/* '"' <qstring> '"' */
1059		do {
1060			dstp += ReadStringB(dstp, srcp+1, &srcp, '"');
1061			if (*srcp == '"') {
1062				srcp++;
1063			} else {
1064				unclosedflag = TRUE;
1065				if (!noerrmode)
1066#if UNIX
1067				{
1068					uchar *mbs = (uchar *)alloca(strlen((char *)sp0) * 2 + 1);
1069					sjis2mbstring((char *)mbs, (char *)sp0);
1070					Error("'\"' expected: %s", mbs);
1071				}
1072#else
1073					Error("'\"' expected: %s", sp0);
1074#endif
1075				else
1076					break;
1077			}
1078		} while (*srcp == '"');
1079				/* �_�u���N�H�[�g���A�����Ă�����P�‚̕�����Ƃ݂Ȃ� */
1080
1081		if (!nevflag) {
1082			vallen = dstp - dst;
1083			val = ValVal(0);
1084		}
1085
1086	} else if (*srcp == '\'') {							/* "'" <echar> "'" */
1087		dstp += ReadStringB(dstp, srcp+1, &srcp, '\'');
1088		if (!nevflag) {
1089			for (p = valstr; p < dstp; p++) {
1090				val *= 0x100;
1091				val += *p;
1092			}
1093		}
1094		dstp = valstr;
1095		if (*srcp == '\'') {
1096			srcp++;
1097		} else {
1098			unclosedflag = TRUE;
1099			if (!noerrmode)
1100#if UNIX
1101				{
1102					uchar *mbs = (uchar *)alloca(strlen((char *)sp0) * 2 + 1);
1103					sjis2mbstring((char *)mbs, (char *)sp0);
1104					Error("\"'\" expected: %s", mbs);
1105				}
1106#else
1107				Error("\"'\" expected: %s", sp0);
1108#endif
1109		}
1110		ValNum(val);
1111	} else if (*srcp == '`') {							/* '`' <expr-prim> */
1112		srcp = SkipExpr(srcp+1, EXPR_PRIM, SKIP_ELSE0);
1113		if (!nevflag) {
1114			dstp += vallen = CopyStrDiff(dstp, SkipSpace(sp0+1), srcp);
1115			val = ValVal(0);
1116		}
1117	} else if (IsKSym1Str(srcp)) {
1118		srcp = SkipKSym2(srcp);
1119		if (IsExprPrimF(srcp)) {						/* <func-call> */
1120			dstp += FuncCall(dstp, sp0, srcp, &srcp, &val);
1121			valstr = dst;
1122			if (!nevflag) {
1123				vallen = dstp - dst;
1124				val = ValVal(val);
1125			}
1126		} else {										/* <usr-var> */
1127			if (!nevflag) {
1128				int len;
1129				p = GetVar1(sp0, srcp-sp0, &len, (exprval_t *)NULL);
1130				dstp += vallen = CopyStrN(dstp, p, len);
1131				val = ValVal(0);
1132			}
1133		}
1134	} else if (*srcp == '.' && !isdigit(*(srcp+1))) {	/* <sys-var> */
1135		srcp++;
1136		if (IsSym1_(*srcp)) {
1137			srcp = SkipSym2(srcp);
1138			if (!nevflag) {
1139				CopyStrDiff(dstp, sp0+1, srcp);
1140				GetVar1(sp0, srcp-sp0, (int *)NULL, &val);
1141				ValNum(val);
1142			}
1143		}
1144#if 0	/* %-form �����Ƃ���ƍ����̂��ƂɂȂ�̂ŁA�p�~ */
1145	} else if (*srcp == '%') {
1146		dstp += EvalPcForm(dstp, srcp+1, &srcp);
1147		valstr = dst;
1148		if (!nevflag) {
1149			vallen = dstp - dst;
1150			val = ValVal(0);
1151		}
1152#endif
1153	} else {											/* <number> */
1154		val = RdNumber(srcp, &p);
1155		if (p == srcp && *p != '.' && !isdigit(*p)) {
1156			/* ���l�Ƃ��ēǂ߂Ȃ���� */
1157			if (!noerrmode)
1158				ExprErr(expr, SkipMoji(p));
1159			val = 0;
1160		} else if (*(srcp = p) == '.' || isalnum(*srcp)) {
1161			val = 0;
1162			for (srcp++; isalnum(*srcp); srcp++);
1163			if (!noerrmode)
1164#if UNIX
1165				ERROR_SE("Illegal number: %s", sp0, srcp);
1166#else
1167				Error("Illegal number: %.*s", (int)(srcp - sp0), sp0);
1168#endif
1169		} else {
1170			ValNum(val);
1171		}
1172	}
1173
1174	assert(dst == valstr);
1175	assert(!nevflag || dstp == valstr);
1176
1177	return val;
1178}
1179
1180/*************************************************************************/
1181
1182int
1183RdNum(const uchar *src, const uchar **endp)
1184{
1185	return (int)strtol((const char *)src, (char**)endp, 10);
1186}
1187
1188
1189exprval_t
1190RdNumber(const uchar *src, const uchar **endp)
1191{
1192	const uchar *srcp = SkipSpace(src);
1193	int sn = *srcp == '+' ? 1 : *srcp == '-' ? -1 : 0;
1194	const uchar *end;
1195	exprval_t val;
1196
1197	if (!*src) {
1198		if (endp)
1199			*endp = src;
1200		return 0;			/* �k��������̒l�� 0 �Ƃ��� */
1201	}
1202
1203	if (sn)
1204		srcp++;
1205
1206	if (*srcp == '0' && isalpha(*(srcp + 1)) && isxdigit(*(srcp + 2))) {
1207		int ch = TOLOWER(*(srcp + 1));
1208		int radix = ch == 'b' ? 2 :
1209					ch == 'o' ? 8 :
1210					ch == 'd' ? 10 :
1211					ch == 'x' ? 16 :
1212					0;
1213		if (radix) {
1214			long ival = (long)strtoul((const char *)srcp + 2, (char**)&end, radix);
1215			if (end != srcp + 2) {
1216				if (endp)
1217					*endp = end;
1218				return sn < 0 ? -ival : ival;
1219			}
1220		}
1221	}
1222#ifdef FLOATEXPR
1223	if ((*srcp == '.' && srcp++, isdigit(*srcp)))
1224		val = strtod((const char *)src, (char **)&end);
1225	else {
1226		val = 0;
1227		end = src;
1228	}
1229#else
1230	val = strtol(src, (char**)&end, 10);
1231#endif
1232	if (end == src) {
1233		/* ���Ƃ��ēǂ߂Ȃ��ꍇ */
1234
1235		if (endp == NULL)
1236			val = (exprval_t)((unsigned)(*src) * 0x100 + *(src+1));
1237
1238#if defined(FLOATEXPR) && defined(_MSC_VER)
1239		/* MSC �̑�֕��������_���Z(/FPa)�g�p�̏ꍇ�̂��� */
1240		if (isdigit(*srcp)) {
1241			/* MSC 6.0 �̑�֕��������_���C�u�������g���ƁAstrtod ��
1242			  �I�[�o�[�t���[�����Ƃ����Ƃ��Ă̔F���������� 0 ��Ԃ��Ă��܂�
1243			  ���� */
1244			val = sn < 0 ? EXPRVAL_MIN : EXPRVAL_MAX;
1245			srcp = SkipDigit(srcp);
1246			if (*srcp=='.')
1247				srcp++;
1248			end = srcp = SkipDigit(srcp);
1249			if (*srcp=='e'||*srcp=='E') {
1250				if (*++srcp == '-') {
1251					val = 0;
1252					srcp++;
1253				} else if (*srcp=='+') {
1254					srcp++;
1255				}
1256				if (isdigit(*srcp)) {
1257					end = SkipDigit(srcp);
1258				} else {
1259					uchar *p = DupStrDiff(src, end);
1260					val = strtod(p, NULL);
1261					XFree((voidstar)p);
1262				}
1263			}
1264		}
1265#endif
1266	}
1267
1268	if (endp)
1269		*endp = end;
1270
1271	return val;
1272}
1273
1274int
1275WtNum(uchar *dst, int num)
1276{
1277	sprintf((char *)dst, "%d", num);
1278	return strlen((char *)dst);
1279}
1280
1281int
1282WtNumber(uchar *dst, exprval_t num)
1283{
1284	sprintf((char *)dst, EXPRVAL_PRINTF_FMT, num);
1285	return strlen((char *)dst);
1286}
1287
1288/******************************* EvalPcForm *******************************/
1289
1290static uchar *
1291SkipPFmt(const uchar *p)
1292{
1293	p += strspn((const char *)p, "-+ #");
1294	p = SkipDigit(p);
1295	if (*p == '.')
1296		p = SkipDigit(p+1);
1297	return (uchar *)p;
1298}
1299
1300static int
1301CommaNum(uchar *dst, const uchar *src)
1302{
1303	uchar *dstp = dst;
1304	const uchar *srcp = src;
1305	const uchar *srcp1;
1306
1307	while (*srcp && !isalnum(*srcp))
1308		MoveMojiAdv(dstp, srcp);
1309
1310	srcp1 = srcp;
1311	while (isalnum(*srcp))
1312		srcp++;
1313
1314	dstp += StrCommaNum(dstp, srcp1, srcp - srcp1, ",", 1, 3);
1315	dstp += CopyStr(dstp, srcp);
1316
1317	return dstp - dst;
1318}
1319
1320static int
1321PFormatS(uchar *dst, const uchar *fmt, int f_type, const uchar *vals, int len)
1322{
1323	if (!*(fmt+1)) {
1324		/* �t�H�[�}�b�g�w�肪�Ȃ���΂��̂܂܃R�s�[ */
1325		return CopyStrN(dst, vals, len);
1326	} else {
1327		const uchar *p, *p2;
1328		int leftflag = (strchr((const char *)fmt+1, '-') != NULL);
1329		int fwidth = atoi((const char *)(p = fmt + 1 + strspn((const char *)fmt+1, "-+ #")));
1330		int zeroflag = !leftflag && fwidth > 0 && *p == '0';
1331		int fprec = (p2 = (uchar *)strchr((const char *)p, '.')) ? atoi((const char *)p2+1) :
1332			((f_type == 'S' || !f_type && !fwidth) && *p) ? fwidth : len;
1333			/* f_type=='S' ��fwidth�w�肪����fprec�w�薳���Ȃ�fprec=fwidth */
1334			/* f_type==0 ��fwidth�w�� 0 ��fprec�w�薳���Ȃ�fprec=0 */
1335
1336		int plen;
1337		int flen;
1338
1339		assert(fwidth >= 0);
1340		assert(fprec >= 0);
1341
1342		if (len <= fprec)
1343			plen = len;
1344		else
1345			plen = NthIsKanji2(vals, fprec) ? fprec - 1 : fprec;
1346
1347		flen = fwidth < plen ? 0 : fwidth - plen;
1348
1349		if (leftflag) {
1350			CopyStrN(dst, vals, plen);
1351			memset(dst + plen, ' ', flen);
1352			*(dst + plen + flen) = '\0';
1353		} else {
1354			memset(dst, zeroflag ? '0' : ' ', flen);
1355			CopyStrN(dst + flen, vals, plen);
1356		}
1357		return plen + flen;
1358	}
1359}
1360
1361
1362int
1363PFormat(uchar *dst, const uchar *f_fmt, const uchar *vals, int len)
1364{
1365	uchar fmt[64];
1366	uchar tmp[64];
1367	exprval_t val = 0;
1368	uchar *fmtp;
1369	int f_type = 0;
1370	int n;
1371
1372	fmt[0] = '%';
1373	if (f_fmt)
1374		strncpy((char *)fmt+1, (const char *)f_fmt, 50);
1375	else
1376		fmt[1] = '\0';
1377
1378	fmtp = StrLast(fmt+1);
1379	if (isalpha(*fmtp)) {
1380		f_type = *fmtp;
1381		*fmtp = '\0';
1382	}
1383
1384	if (f_type != 's' && f_type != 'S')
1385		val = RdNumber(vals, (const uchar **)NULL);
1386
1387	fmtp = SkipPFmt(fmt+1);
1388	if (*fmtp) {
1389		if (!noerrmode)
1390#if UNIX
1391		{
1392			uchar *mbs = (uchar *)alloca(strlen((char *)f_fmt) * 2 + 1);
1393			sjis2mbstring((char *)mbs, (char *)f_fmt);
1394			Error("Invalid Format: %s", mbs);
1395		}
1396#else
1397			Error("Invalid Format: %s", f_fmt);
1398#endif
1399		else {
1400			fmtp = fmt+1;
1401			*fmtp = '\0';
1402		}
1403	}
1404	switch (f_type) {
1405	case 'S':
1406	case 's':
1407	case 0:
1408	_case_s:
1409		return PFormatS(dst, fmt, f_type, vals, len);
1410	case 'd':
1411		sprintf((char *)dst, strcat((char *)fmt, "ld"), (long)val);
1412		return strlen((char *)dst);
1413	case 'u':
1414		sprintf((char *)dst, strcat((char *)fmt, "lu"), (unsigned long)val);
1415		return strlen((char *)dst);
1416	case 'o':
1417		sprintf((char *)dst, strcat((char *)fmt, "lo"), (unsigned long)val);
1418		return strlen((char *)dst);
1419	case 'x':
1420		sprintf((char *)dst, strcat((char *)fmt, "lx"), (unsigned long)val);
1421		return strlen((char *)dst);
1422	case 'X':
1423		sprintf((char *)dst, strcat((char *)fmt, "lX"), (unsigned long)val);
1424		return strlen((char *)dst);
1425	case 'c':
1426		tmp[n = SetMoji((unsigned)val, tmp)] = '\0';	/* �������當����ɕϊ� */
1427		return PFormat(dst, (uchar *)strcat((char *)fmt+1, "s"), tmp, n);
1428
1429	case 'O':				/* Ordinal */
1430		n = MkNthNum(tmp, (long)val);
1431		return PFormat(dst, (uchar *)strcat((char *)fmt+1, "s"), tmp, n);
1432	case 'k':				/* kansuuji */
1433		n = StrKanjiNum(tmp, vals, len);
1434		return PFormat(dst, (uchar *)strcat((char *)fmt+1, "s"), tmp, n);
1435	case 'C':				/* numer whith thousand sep */
1436		n = CommaNum(tmp, vals);
1437		return PFormat(dst, (uchar *)strcat((char *)fmt+1, "s"), tmp, n);
1438	case 'r':
1439	case 'R':
1440		if (val < 1 || val > 3999)
1441			goto _case_s;
1442
1443		n = MkRomNum(tmp, (int)val, isupper(f_type));
1444		return PFormat(dst, (uchar *)strcat((char *)fmt+1, "s"), tmp, n);
1445	case 'a':
1446	case 'A':
1447		if (val < 1 || val > 26)
1448			goto _case_s;
1449
1450		sprintf((char *)dst, strcat((char *)fmt, "c"), (f_type - 1) + (int)val);
1451
1452		return strlen((char *)dst);
1453
1454#ifdef FLOATEXPR
1455	case 'f':
1456	case 'e':
1457	case 'E':
1458	case 'g':
1459	case 'G':
1460		*fmtp++ = f_type;
1461		*fmtp = '\0';
1462
1463		sprintf((char *)dst, (char *)fmt, (double)val);
1464
1465		return strlen((char *)dst);
1466#endif
1467
1468	default:
1469		if (!noerrmode)
1470			Error("Unknown format type: %c", f_type);
1471		return 0;
1472	}
1473}
1474
1475
1476/**************************************/
1477
1478static int
1479CopyEnvValN(uchar *dst, const uchar *name, int nlen)
1480{
1481	uchar *val = NULL;
1482	uchar var[128];
1483	CopyStrN(var, name, min(nlen, 127));
1484	StrUpper(var, var);
1485	val = (uchar *)getenv((char *)var);
1486
1487	if (val) {
1488		return CopyStr(dst, val);
1489	} else {
1490		*dst = 0;
1491		return 0;
1492	}
1493}
1494
1495
1496int
1497CopyEnvVal(uchar *dst, const uchar *name)
1498{
1499	return CopyEnvValN(dst, name, strlen((const char *)name));
1500}
1501
1502int
1503EvalPcForm(uchar *dst, const uchar *src, const uchar **endp)
1504/* src: <%-form2>   -- '%' �̎��̕������w�� */
1505{
1506	uchar *dstp = dst;
1507	const uchar *srcp = src;
1508	const uchar *sp0 = srcp;
1509	const uchar *sp1;
1510	int len;
1511	int n;
1512
1513	uchar *fbuf = NULL;			/* �ϊ������p�o�b�t�@�imalloc �ŗ̈�m�ہj */
1514	uchar *vbuf = NULL;			/* �ϐ��i�[�p�o�b�t�@�imalloc �ŗ̈�m�ہj */
1515
1516	if (IsExprPrimF(srcp)) {
1517		/*
1518		 * '%' <expr-prim-f>
1519		 */
1520		dstp += EvalExpr(dstp, srcp, &srcp, EXPR_PRIM);
1521
1522	} else if (*srcp != '-' ? IsSym2_(*srcp) : IsSym2_(*(srcp+1))) {
1523		/* '%' �̌オ�p�����܂��� '-'�t���̉p�����Ȃ� */
1524		if (*srcp == '-')
1525			srcp++;
1526		sp1 = SkipDigit(srcp);
1527		srcp = SkipSym2(srcp);
1528
1529		if (sp0 == sp1 && *srcp == '%') {
1530			/*
1531			 *  '%' <env-var> '%'
1532			 */
1533			if (!nevflag) {
1534				dstp += CopyEnvValN(dstp, sp0, srcp - sp0);
1535			}
1536			srcp++;
1537		} else if (sp1 == srcp) {
1538			/*
1539			 *	'%' ['-'] <arg-#>
1540			 */
1541			n = RdNum(sp0, &srcp);
1542			if (!nevflag)
1543				dstp += CopyArg(dstp, n);
1544		} else {
1545			/*
1546			 *  '%' ['-'] [<f-width>] <func-call*>
1547			 */
1548			if (sp1 > sp0)
1549				fbuf = DupStrDiff(sp0, sp1);
1550			len = FuncCall(dstp, sp1, srcp, &srcp, (exprval_t *)NULL);
1551			if (!nevflag) {
1552				if (fbuf) {
1553					vbuf = DupStrN(dstp, len);
1554					dstp += PFormat(dstp, fbuf, vbuf, len);
1555				} else {
1556					dstp += len;
1557				}
1558			}
1559		}
1560	} else switch (*srcp) {
1561
1562#if 0	/* �g�ݍ��݊֐� cmd(str), _(str) �ɖ����䂸��A�p�~ */
1563	case '.':
1564		/*
1565		 * '%' '.' <expr-prim>
1566		 */
1567		vbuf = AEvalExpr(&len, srcp+1, &srcp, EXPR_PRIM);
1568		if (!nevflag)
1569			Command(vbuf);
1570		break;
1571#endif
1572	case ':':
1573		/*
1574		 * '%' ':' <format> <expr-prim-f>
1575		 */
1576		srcp = SkipSym2(SkipPFmt(srcp+1));
1577		fbuf = DupStrDiff(sp0+1, srcp);
1578		if (IsExprPrimF(srcp)) {
1579			vbuf = AEvalExpr(&len, srcp, &srcp, EXPR_PRIM);
1580			if (!nevflag) {
1581				dstp += PFormat(dstp, fbuf, vbuf, len);
1582			}
1583		}
1584		break;
1585
1586#if 0	/* �g�ݍ��݊֐� fn(path, fname) �����������̂ŁA����̓{�c */
1587	case '/':
1588		/*
1589		 * '%' '/'
1590		 */
1591		srcp++;
1592		if (!nevflag) {
1593			if (*(dstp - 1) != DIRSLASH && *(dstp - 1) != ALTDIRSLASH)
1594				*dstp++ = DIRSLASH;
1595		}
1596		break;
1597#endif
1598
1599	case '\\':
1600		/*
1601		 * '%' <\-sequence>
1602		 */
1603		dstp += ReadEscSequence(dstp, srcp+1, &srcp);
1604		break;
1605	case '%':
1606		/*
1607		 * '%' '%'
1608		 */
1609		srcp++;
1610		if (!nevflag)
1611			*dstp++ = '%';
1612		break;
1613	case '<':
1614		/*
1615		 * '%' '<'
1616		 */
1617		srcp++;
1618		if (!nevflag)
1619			*dstp++ = '{';
1620		break;
1621	case '>':
1622		/*
1623		 * '%' '>'
1624		 */
1625		srcp++;
1626		if (!nevflag)
1627			*dstp++ = '}';
1628		break;
1629	default:
1630		/*
1631		 * '%'
1632		 */
1633		/* '%' �̌オ���̑��̕����Ȃ�A���̂܂� '%' ��L���ɂ��� */
1634		if (!nevflag)
1635			*dstp++ = '%';
1636	}
1637	XFree((voidstar)fbuf);
1638	XFree((voidstar)vbuf);
1639
1640	if (endp) *endp = srcp;
1641	if (!nevflag)
1642		*dstp = 0;
1643	assert(!nevflag || dstp == dst);
1644	return dstp - dst;
1645}
1646
1647
1648
1649
1650/******************************** FuncCall ********************************/
1651
1652#if UNIX
1653#define ERROR_SS(fmt,n,s)												\
1654	do {																\
1655		uchar *_n, *_s;													\
1656		_n = (uchar *)alloca(strlen((char *)(n)) * 2 + 1);				\
1657		sjis2mbstring((char *)_n, (char *)(n));							\
1658		_s = (uchar *)alloca(strlen((char *)(s)) * 2 + 1);				\
1659		sjis2mbstring((char *)_s, (char *)(s));							\
1660		Error((uchar *)(fmt), _n, _s);									\
1661	} while (0)
1662#define ArgErr()		ERROR_SS("Invalid argument: %s%s", name, src)
1663#else
1664#define ArgErr()		Error(f_ArgErr, name, src)
1665static uchar f_ArgErr[] = "Invalid argument: %s%s";
1666#endif
1667
1668#if UNIX
1669#define ManyArgErr() \
1670	ERROR_SS((IsExpr(srcp) ? "Too many arguments: %s%s" : "Invalid argument: %s%s"), name, src)
1671#else
1672#define ManyArgErr()	Error(IsExpr(srcp) ? f_ManyArgErr : f_ArgErr, \
1673								name, src)
1674static uchar f_ManyArgErr[] = "Too many arguments: %s%s";
1675#endif
1676
1677static int
1678FuncCallSub(uchar *dst, const uchar *name, const uchar *src, const uchar **endp, exprval_t *fretvalp)
1679{
1680	uchar *dstp = dst;
1681	const uchar *srcp = src;
1682	uchar *vbuf = NULL;
1683	int   len = 0;
1684	uchar *p;
1685	sffnp_t 	funcp;
1686	sftype_t	sftype;
1687	int n1 = 0;
1688	int n2 = 0;
1689	exprval_t x1 = 0;
1690	exprval_t x2 = 0;
1691	uchar *vbuf2 = NULL;
1692	int len2 = 0;
1693	exprval_t val = 0;
1694	int fargcnt = 0;
1695
1696	assert(!nevflag);
1697	assert(src != NULL);
1698
1699	if ((sftype = GetSFunc(&funcp, name)) != SF_UNKNOWN) {
1700		/*
1701		 * <func> {<func-args> | <expr-prim-f>}
1702		 */
1703		if (*srcp != '(') {
1704			/* ���������ʂň͂܂�Ă��Ȃ��ꍇ */
1705			/* ��ˆ����̂݉”\ */
1706			if (IsExprPrimF(srcp)) {
1707				fargcnt++;
1708				vbuf = AEvalExpr(&len, srcp, &srcp, EXPR_PRIM);
1709				if (sftype < SF_S) {
1710					x1 = exprval;
1711					if (x1 > INT_MIN && x1 < INT_MAX)
1712						n1 = (int)x1;
1713				}
1714			}
1715		} else {
1716			/*
1717			 * <func-args> : '(' [ <expr-asgn> { ',' <expr-asgn> }* ] ')'
1718			 */
1719			/* ���ʂň͂܂�Ă���ꍇ */
1720			srcp++;
1721			CutSpace(srcp);
1722			if (sftype >= SF_S && IsExpr(srcp)) {
1723				/* ����������̏��� */
1724				fargcnt++;
1725				vbuf = AEvalExpr(&len, srcp, &srcp, EXPR_SEMIMAX);
1726				if (*CutSpace(srcp) == ',')
1727					srcp++;
1728
1729				if (sftype >= SF_Sn_Sn && *CutSpace(srcp) != ')') {
1730					/* ������������Q�‚Ƃ�֐��̏ꍇ */
1731					fargcnt++;
1732					vbuf2 = AEvalExpr(&len2, srcp, &srcp, EXPR_SEMIMAX);
1733					if (*CutSpace(srcp) == ',')
1734						srcp++;
1735				}
1736			}
1737			if (*CutSpace(srcp) != ')') {
1738				/* ���l�����̏��� */
1739				if ((sftype == SF_0 || sftype == SF_S || sftype == SF_Sn
1740									|| sftype == SF_Sn_Sn) && !noerrmode) {
1741					ManyArgErr();
1742				}
1743				fargcnt++;
1744				x1 = EvalExprVal(srcp, &srcp, EXPR_SEMIMAX);
1745				if (x1 >= INT_MIN && x1 <= INT_MAX)
1746					n1 = (int)x1;
1747				if (*CutSpace(srcp) == ',')
1748					srcp++;
1749				if (*CutSpace(srcp) != ')') {
1750					if ((sftype == SX_X || sftype == SF_X || sftype == SF_Sn_N
1751										|| sftype == SF_Sn_Sn_N)&&!noerrmode) {
1752						ManyArgErr();
1753					}
1754					fargcnt++;
1755					x2 = EvalExprVal(srcp, &srcp, EXPR_SEMIMAX);
1756					if (x2 >= INT_MIN && x2 <= INT_MAX)
1757						n2 = (int)x2;
1758					if (*CutSpace(srcp) == ',')
1759						srcp++;
1760				}
1761			}
1762			if (*CutSpace(srcp) == ')')
1763				srcp++;
1764			else {
1765				if (!noerrmode)
1766					ManyArgErr();
1767				srcp = SkipExpr(src, EXPR_PRIM, SKIP_NOERR);
1768			}
1769		}
1770		if (sftype >= SF_S && !vbuf)
1771			vbuf = DupStr("");
1772
1773		fargc = fargcnt;
1774
1775		switch (sftype) {
1776		case SF_0:
1777			len = ((sf00fnp_t)funcp)(dstp);
1778			break;
1779		case SF_X:
1780			len = ((sf01fnp_t)funcp)(dstp, x1);
1781			break;
1782		case SF_X_X:
1783			len = ((sf02fnp_t)funcp)(dstp, x1, x2);
1784			break;
1785		case SF_S:
1786			len = ((sfs0fnp_t)funcp)(dstp, vbuf);
1787			break;
1788		case SF_Sn:
1789			len = ((sf10fnp_t)funcp)(dstp, vbuf, len);
1790			break;
1791		case SF_Sn_N:
1792			len = ((sf11fnp_t)funcp)(dstp, vbuf, len, n1);
1793			break;
1794		case SF_Sn_N_N:
1795			len = ((sf12fnp_t)funcp)(dstp, vbuf, len, n1, n2);
1796			break;
1797		case SF_Sn_Sn:
1798			len = ((sf20fnp_t)funcp)(dstp, vbuf, len, vbuf2, len2);
1799			break;
1800		case SF_Sn_Sn_N:
1801			len = ((sf21fnp_t)funcp)(dstp, vbuf, len, vbuf2, len2, n1);
1802			break;
1803		case SF_Sn_Sn_N_N:
1804			len = ((sf22fnp_t)funcp)(dstp, vbuf, len, vbuf2, len2, n1, n2);
1805			break;
1806		case SX_X:
1807			val = ((sfx1fnp_t)funcp)(x1);
1808			len = (val == 0 || !fretvalp) ? WtNumber(dstp, val) : 0;
1809			break;
1810		case SX_X_X:
1811			val = ((sfx2fnp_t)funcp)(x1, x2);
1812			len = (val == 0 || !fretvalp) ? WtNumber(dstp, val) : 0;
1813			break;
1814		default:
1815			assert(FALSE);
1816		}
1817		*(dstp += len) = '\0';
1818
1819	} else if ((p = GetSFVar(&len, name)) != NULL) {
1820		/*
1821		 * <func0arg>
1822		 */
1823		dstp += CopyStrN(dstp, p, len);
1824		if (*srcp == '(' && (srcp++, *CutSpace(srcp) == ')')) {
1825			srcp++;
1826		} else {
1827			srcp = src;
1828			if (fretvalp || IsExprPrimF(srcp)) {
1829				/* �֐��Ăяo���`���̏ꍇ */
1830				if (!noerrmode)
1831					ManyArgErr();
1832				srcp = SkipExpr(srcp, EXPR_PRIM, SKIP_ELSE0);
1833			}
1834		}
1835	} else if (!noerrmode) {
1836#if UNIX
1837		uchar *mbs = (uchar *)alloca(strlen((char *)name) * 2 + 1);
1838		sjis2mbstring((char *)mbs, (char *)name);
1839		Error("Unknown function: %s", mbs);
1840#else
1841		Error("Unknown function: %s", name);
1842#endif
1843	}
1844	XFree((voidstar)vbuf2);
1845	XFree((voidstar)vbuf);
1846	if (endp) *endp = srcp;
1847	if (fretvalp) *fretvalp = val;
1848	return dstp - dst;
1849}
1850
1851
1852static int
1853FuncCall(uchar *dst, const uchar *name, const uchar *src, const uchar **endp, exprval_t *fretvalp)
1854{
1855	const uchar *srcp = src;
1856	macro_t		*macp;
1857	int			len = 0;
1858
1859	assert(nevflag || dst != NULL);
1860	assert(src != NULL);
1861
1862	name = DupStrDiff(name, src);
1863
1864	unclosedflag = FALSE;	/* �������X�g�̊��ʂ��‚��Ă��邩�̃`�F�b�N�p */
1865
1866	if (nevflag || (macp = GetMacro(name)) != NULL) {
1867		if (IsExprPrimF(srcp)) {
1868			srcp = SkipExpr(src, EXPR_PRIM, SKIP_NOERR);
1869			if (unclosedflag && !nevflag && !noerrmode) {
1870				srcp = SkipExpr(src, EXPR_PRIM, SKIP_NORMAL);
1871				/* ����ŃG���[�ɂȂ��Ă����ɂ͂��Ȃ��͂� */
1872				assert(FALSE);
1873			}
1874		}
1875		if (!nevflag && !unclosedflag) {
1876			uchar *vbuf;
1877			vbuf = (*src == '(' && srcp != src)
1878						  ? DupStrDiff(src+1, srcp-1)
1879						  : DupStrDiff(src, srcp);
1880			len = FuncMacroCall(dst, macp, vbuf);
1881			unclosedflag = FALSE;
1882			XFree((voidstar)vbuf);
1883		}
1884		if (fretvalp) *fretvalp = 0;
1885		if (endp) *endp = srcp;
1886	} else {
1887		len = FuncCallSub(dst, name, src, endp, fretvalp);
1888	}
1889	XFree((voidstar)name);
1890	return len;
1891}
1892
1893
1894/******************************* EvalString *******************************/
1895
1896int
1897EvalString(uchar *dst, const uchar *src)
1898/* ������Ɂq%-�ϊ��r���{������ł̃R�s�[���s�� */
1899/* dst �Ɋi�[�����������i�k���������j��Ԃ� */
1900{
1901	return EvalStringB(dst, src, (const uchar **)NULL, 0);
1902}
1903
1904int
1905EvalStringB(uchar *dst, const uchar *src, const uchar **endp, int bflag)
1906/* bflag ���^�Ȃ�A'{' �̎��̕����ŌĂ΂�āA�Ή����� '}' �܂œǂށB
1907 * ���̏ꍇ�A�Ō�� '}'�̓R�s�[���Ȃ��œǂݎ̂Ă�B
1908 */
1909{
1910	uchar *dstp = dst;
1911	const uchar *srcp = src;
1912	int nestlevel = 1;
1913	unsigned c;
1914
1915	assert(nevflag || dst != NULL);
1916	assert(src != NULL);
1917
1918	unclosedflag = FALSE;
1919
1920	while (*srcp) {
1921		c = RdMoji(srcp);
1922		if (c == '%')
1923			dstp += EvalPcForm(dstp, srcp, &srcp);
1924		else {
1925			if (bflag) {
1926				if (c == '{')
1927					nestlevel++;
1928				else if (c == '}') {
1929					if (--nestlevel == 0)
1930						break;					/* �����܂� */
1931				}
1932			}
1933			if (!nevflag)
1934				dstp += SetMoji(c, dstp);
1935		}
1936	}
1937	if (bflag && nestlevel != 0) {
1938		unclosedflag = TRUE;
1939		if (!noerrmode)
1940#if UNIX
1941		{
1942			uchar *mbs = (uchar *)alloca(strlen((char *)src) * 2 + 1);
1943			sjis2mbstring((char *)mbs, (char *)src);
1944			Error("'}' expected: {%s", mbs);
1945		}
1946#else
1947			Error("'}' expected: {%s", src);
1948#endif
1949	} else {
1950		unclosedflag = FALSE;
1951	}
1952	if (endp) *endp = srcp;
1953	if (!nevflag) *dstp = 0;
1954	assert(!nevflag || dstp == dst);
1955	return dstp - dst;
1956}
1957
1958
1959int
1960EvalStringN(uchar *dst, const uchar *src, int n)
1961{
1962	uchar *dstp = dst;
1963	uchar *dp1 = dst;
1964	const uchar *srcp = src;
1965	const uchar *src_e = src + n;
1966
1967	assert(dst != NULL);
1968	assert(src != NULL);
1969	assert(n >= 0);
1970
1971	while (srcp < src_e) {
1972		dp1 = dstp;
1973		if (*srcp == '%')
1974			dstp += EvalPcForm(dstp, srcp+1, &srcp);
1975		else
1976			MoveMojiAdv(dstp, srcp);
1977	}
1978	if (srcp > src_e)
1979		dstp = dp1;
1980	*dstp = 0;
1981	return dstp - dst;
1982}
1983
1984
1985/**************************************************************************/
1986
1987
1988
1989int
1990EvalExprStr(uchar *dst, const uchar *src)
1991{
1992	return EvalExpr(dst, src, (const uchar **)NULL, EXPR_MAX);
1993}
1994
1995
1996exprval_t
1997EvalExprVal(const uchar *src, const uchar **endp, evlev_t evlevel)
1998/* ����]�����Đ��Ƃ��Ă̒l��Ԃ� */
1999{
2000	uchar *vbuf = AEvalExpr((int *)NULL, src, endp, evlevel);
2001	XFree((voidstar)vbuf);
2002	return exprval;
2003}
2004
2005uchar *
2006SkipExpr(const uchar *src, evlev_t evlevel, skipmode_t skipmode)
2007/* ����ǂݔ�΂� */
2008{
2009	int 	nevflag0 = nevflag;
2010	int 	noerrmode0 = noerrmode;
2011	uchar 	*vbuf;
2012	const uchar	*srcp;
2013	const uchar	*sp0 = SkipSpace(src);
2014
2015	nevflag = TRUE;
2016	noerrmode = (skipmode != SKIP_NORMAL);
2017	vbuf = AEvalExpr((int *)NULL, sp0, &srcp, evlevel);
2018	XFree((voidstar)vbuf);
2019
2020	if (unclosedflag || srcp == sp0) {
2021		switch (skipmode) {
2022		case SKIP_ELSE0:
2023			srcp = src;
2024			break;
2025		case SKIP_ELSE1:
2026			srcp = SkipMoji(sp0);
2027			break;
2028		default:
2029			;
2030		}
2031	}
2032	noerrmode = noerrmode0;
2033	nevflag = nevflag0;
2034	return (uchar*)srcp;
2035}
2036
2037/**************************************/
2038
2039/* AEval... �̈�̊m�ەt�� */
2040
2041#define AllocEvalBuf()	(nevflag ? (uchar *)NULL : (uchar *)XMalloc(evalbufsize))
2042
2043static void
2044CheckEvalBufLen(int len)
2045{
2046	assert(!nevflag || len == 0);
2047	if (len >= (int)evalbufsize)
2048		FError("Eval buffer over");
2049}
2050
2051uchar *
2052AEvalExpr(int *lenp, const uchar *src, const uchar **endp,
2053													evlev_t evlevel)
2054{
2055	int len;
2056	uchar *dst = AllocEvalBuf();
2057	len = EvalExpr(dst, src, endp, evlevel);
2058	CheckEvalBufLen(len);
2059	if (lenp) *lenp = len;
2060	return (uchar *)XRealloc((voidstar)dst, len+1);
2061}
2062
2063uchar *
2064AEvalPcForm(int *lenp, const uchar *src, const uchar **endp)
2065{
2066	int len;
2067	uchar *dst = AllocEvalBuf();
2068	len = EvalPcForm(dst, src, endp);
2069	CheckEvalBufLen(len);
2070	if (lenp) *lenp = len;
2071	return (uchar *)XRealloc((voidstar)dst, len+1);
2072}
2073
2074uchar *
2075AEvalString(int *lenp, const uchar *src)
2076{
2077	return AEvalStringB(lenp, src, (const uchar **)NULL, 0);
2078}
2079
2080uchar *
2081AEvalStringB(int *lenp, const uchar *src, const uchar **endp, int bflag)
2082{
2083	int len;
2084	uchar *dst = AllocEvalBuf();
2085	len = EvalStringB(dst, src, endp, bflag);
2086	CheckEvalBufLen(len);
2087	if (lenp) *lenp = len;
2088	return (uchar *)XRealloc((voidstar)dst, len+1);
2089}
2090
2091uchar *
2092AEvalStringN(int *lenp, const uchar *src, int n)
2093{
2094	int len;
2095	uchar *dst = AllocEvalBuf();
2096	len = EvalStringN(dst, src, n);
2097	CheckEvalBufLen(len);
2098	if (lenp) *lenp = len;
2099	return (uchar *)XRealloc((voidstar)dst, len+1);
2100}
2101
2102uchar *
2103AEvalExprStr(int *lenp, const uchar *src)
2104{
2105	int len;
2106	uchar *dst = AllocEvalBuf();
2107	len = EvalExprStr(dst, src);
2108	CheckEvalBufLen(len);
2109	if (lenp) *lenp = len;
2110	return (uchar *)XRealloc((voidstar)dst, len+1);
2111}
2112
2113uchar *
2114AReadString(int *lenp, const uchar *src)
2115{
2116	return AReadStringB(lenp, src, (const uchar **)NULL, EOF);
2117}
2118
2119uchar *
2120AReadStringB(int *lenp, const uchar *src,const uchar **endp,int brkchr)
2121{
2122	int len;
2123	uchar *dst = AllocEvalBuf();
2124	len = ReadStringB(dst, src, endp, brkchr);
2125	CheckEvalBufLen(len);
2126	if (lenp) *lenp = len;
2127	return (uchar *)XRealloc((voidstar)dst, len+1);
2128}
2129
2130/*
2131 * Local variables:
2132 * mode: c
2133 * c-indent-level: 4
2134 * c-continued-statement-offset: 4
2135 * c-brace-offset: -4
2136 * c-argdecl-indent: 4
2137 * c-label-offset: -4
2138 * tab-width: 4
2139 * tab-stop-list: (4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80)
2140 * End:
2141 */
2142