1 /* xmacro.c */
2 /*****************************************************************************
3 					�ԣ�������У���������أԣ�
4 
5 						�Υޥ����ޥ�ɡ��ѿ��ν�����
6 *****************************************************************************/
7 
8 #include "xtr.h"
9 
10 
11 /*************************** User variable ****************************/
12 
13 /* �ѿ�̾ var ���������ͭ�����뤫 */
14 #define IsLocalVar(var)		(islower(*(var)) || *(var) == '$')
15 
16 uchar *
GetVar(const uchar * name,int * lenp)17 GetVar(const uchar *name, int *lenp)
18 /* �ѿ����ͤ���Ф���̤����ʤ顢��ʸ������֤� */
19 /* NULL �Ǥʤ� lenp ��Ϳ����줿�顢�����Ĺ�����Ǽ���� */
20 {
21 	var_t  *p;
22 
23 	assert(name != NULL);
24 
25 	p = IsLocalVar(name) ? localvarlist : varlist;
26 	while (p) {
27 		if (equ(name, p->name)) {
28 			if (lenp)
29 				*lenp = p->len;
30 			return p->val;
31 		}
32 		p = p->prev;
33 	}
34 	if (lenp) *lenp = 0;
35 	return "";
36 }
37 
38 
39 void
PutVar(const uchar * name,const uchar * val,int len)40 PutVar(const uchar *name, const uchar *val, int len)
41 /* �ѿ� name ���� val ���������� */
42 /* �⤷��val �� NULL �ޤ��� len �� 0 �ʤ顢�ѿ��������� */
43 {
44 	int islocalvar = IsLocalVar(name);
45 
46 	var_t  **pp;
47 	var_t  *p;
48 
49 	assert(name != NULL);
50 
51 	if (len == 0)
52 		val = NULL;
53 
54 	pp = islocalvar ? &localvarlist : &varlist;
55 	p = *pp;
56 	while (p) {
57 		if (equ(name, p->name)) {
58 			if (val) {
59 				/* �ͤ��դ��ؤ� */
60 				XFree((voidstar)p->val);
61 				p->val = DupStrN(val, len);
62 				p->len = len;
63 			} else {
64 				/* ��� */
65 				*pp = p->prev;
66 				XFree((voidstar)p->name);
67 				XFree((voidstar)p->val);
68 				XFree((voidstar)p);
69 			}
70 			return;
71 		}
72 		pp = &p->prev;
73 		p = *pp;
74 	}
75 
76 	/* ̤����ѿ��ʤ� */
77 	pp = islocalvar ? &localvarlist : &varlist;
78 	if (val) {
79 		p = (var_t *)XMalloc(sizeof(var_t));
80 		p->name = DupStr(name);
81 		p->val = DupStrN(val, len);
82 		p->len = len;
83 		p->prev = *pp;
84 		*pp = p;
85 	}
86 }
87 
88 
89 /************************ Macro command processing ************************/
90 
91 /* �ޥ���while�롼�ס��֥�å�����ȴ���뤫�餯�� */
92 static enum BREAK_LEVEL {
93 	B_RETURN = -1,
94 	B_NOBREAK,
95 	B_CONTINUE,
96 	B_BREAK,
97 } break_level;
98 
99 int
CopyArg(uchar * dst,int n)100 CopyArg(uchar *dst, int n)
101 {
102 	if (n < 0)
103 		n = margc + n + 1;
104 
105 	if (margv && n <= margc) {
106 		return CopyStrN(dst, margv[n].s, margv[n].len);
107 	} else {
108 		*dst = 0;
109 		return 0;
110 	}
111 }
112 
113 
114 /**************************************/
115 
116 static void Cmd_if(const uchar *argp);
117 static void Cmd_while(const uchar *argp);
118 static void Cmd_for(const uchar *argp);
119 static void Cmd_break(const uchar *argp);
120 static void Cmd_continue(const uchar *argp);
121 static void Cmd_return(const uchar *argp);
122 
123 typedef void (*cmdfnp_t)(const uchar *argp);
124 
125 static struct SYSCMDTBL {
126 	uchar *name;
127 	cmdfnp_t fnp;
128 } syscmdtbl[] = {
129 	{"if",			Cmd_if},
130 	{"while",		Cmd_while},
131 	{"for",			Cmd_for},
132 	{"break",		Cmd_break},
133 	{"continue",	Cmd_continue},
134 	{"return",		Cmd_return},
135 };
136 
137 #define N_SYSCMD		  (sizeof(syscmdtbl) / sizeof(syscmdtbl[0]))
138 
139 #define MkSysCmdMacp(i)		((macro_t *)(ulong)((i)+1))
140 #define IsSysCmdMacp(p)		((ulong)(p) <= (ulong)N_SYSCMD)
141 #define SysCmdFnp(macp)		(syscmdtbl[(int)(long)(macp)-1].fnp)
142 #define SysCmdName(macp)		(syscmdtbl[(int)(long)(macp)-1].name)
143 
144 /**************************************/
145 
146 macro_t *
GetMacro(const uchar * name)147 GetMacro(const uchar *name)
148 /* �ޥ����������Ф� */
149 {
150 	macro_t  *p = macrolist;
151 	int  i;
152 
153 	assert(name != NULL);
154 
155 	while (p) {
156 		if (equ(name, p->name)) {
157 			return p;
158 		}
159 		p = p->prev;
160 	}
161 	for (i = 0; i < N_SYSCMD; i++) {
162 		if (equ(syscmdtbl[i].name, name))
163 			return MkSysCmdMacp(i);
164 	}
165 	return NULL;
166 }
167 
168 
169 /**************************************************************************/
170 
171 
172 void
FreeMargv(int argc,marg_t * argv)173 FreeMargv(int argc, marg_t *argv)
174 {
175 	int i;
176 	for (i = argc; i >= 0; --i)
177 		XFree((voidstar)argv[i].s);
178 	XFree((voidstar)argv);
179 }
180 
181 
182 #define IsEvalArg(arg)	(*(arg)=='(' || *(arg)=='{')
183 
184 static uchar *
MakeBlockArg(int * lenp,uchar ** nextp)185 MakeBlockArg(int *lenp, uchar **nextp)
186 {
187 	int	bufsize = 1024;
188 	uchar *buf = (uchar *)XMalloc(bufsize);
189 	uchar *bp = buf;
190 	uchar *cmdln;
191 	uchar *p;
192 	int len = 0;
193 	unsigned c;
194 	assert(lenp != NULL);
195 	assert(nextp != NULL);
196 
197 	for ( ; ; ) {
198 		c = GetChr();
199 		if (c == EOF2) {
200 			*nextp = NULL;
201 			break;
202 		}
203 		if ((int)c == cmddot_mchar || cmddot_char && (int)c == cmddot_char) {
204 			cmdln = GetCommandLine(&len);
205 			if (CheckBlockEnd(cmdln, len, FALSE, (const uchar **)&p)) {
206 				CutSpace(p);
207 				*nextp = *p ? DupStrDiff(p, cmdln + len) : NULL;
208 				XFree((voidstar)cmdln);
209 				break;
210 			}
211 			if (bp + (len+2) - buf >= bufsize) {
212 				uchar *buf2 = (uchar *)XRealloc((voidstar)buf, bufsize += len + 1024);
213 				bp = buf2 + (bp - buf);
214 				buf = buf2;
215 			}
216 			*bp++ = cmddot_mchar;
217 			bp += CopyStrN(bp, cmdln, len);
218 			*bp++ = '\n';
219 			*bp = '\0';
220 			XFree((voidstar)cmdln);
221 		} else {
222 			UngetChr(c);
223 			len = GetLine();
224 			if (bp + len - buf >= bufsize) {
225 				uchar *buf2 = (uchar *)XRealloc((voidstar)buf, bufsize += len + 1024);
226 				bp = buf2 + (bp - buf);
227 				buf = buf2;
228 			}
229 			bp += CopyStrN(bp, ibuf, len);
230 		}
231 		ILineNoCount();
232 	}
233 	*lenp = bp - buf;
234 	return (uchar *)XRealloc((voidstar)buf, (bp - buf) + 1);
235 }
236 
237 
238 /**************************************/
239 
240 #if UNIX
241 #define ERROR_SS(fmt,n,s)												\
242 	do {																\
243 		uchar *_n, *_s;													\
244 		_n = (uchar *)alloca(strlen((char *)(n)) * 2 + 1);				\
245 		sjis2mbstring((char *)_n, (char *)(n));							\
246 		_s = (uchar *)alloca(strlen((char *)(s)) * 2 + 1);				\
247 		sjis2mbstring((char *)_s, (char *)(s));							\
248 		Error((fmt), _n, _s);											\
249 	} while (0)
250 #endif
251 
252 /* mfflag �������� */
253 #define M_COMMAND		0
254 #define M_FUNCTION		1
255 #define M_SYSCMD		2
256 
257 static const uchar *macname = NULL;		/* �ޥ���̾�����ʥ��顼ɽ���ѡ� */
258 
259 static marg_t *
MakeMargv(int * argcp,const uchar * argp,matype_t typ,int maxargc,int mfflag)260 MakeMargv(int *argcp, const uchar *argp, matype_t typ, int maxargc, int mfflag)
261 /* ���ޥ�ɰ����٥������������ */
262 {
263 	marg_t argvb[MAXMARGC+1];
264 	marg_t *newargv;
265 	int  argc = 0;
266 	const uchar *p = NULL;
267 	const uchar *p0;
268 	const uchar *p1;
269 	uchar *bp = NULL;
270 	int len;
271 	uchar *nextbuf = NULL;
272 	const uchar *mname = macname ? macname : (uchar *)"";
273 
274 	assert(argcp != NULL);
275 	assert(argp != NULL);
276 	assert(maxargc <= MAXMARGC);
277 
278 	CutSpace(argp);
279 	argvb[0].len = len = strlen((const char *)argp);
280 	argvb[0].s = DupStrN(argp, len);
281 	argvb[0].typ = MA_VERBATIM;
282 
283 	if (maxargc >= 0) {
284 		p = argp;
285 		while (*p && argc < MAXMARGC) {
286 			argc++;
287 			p1 = p0 = p;
288 			if (mfflag == M_FUNCTION || typ == MA_EXPR) {
289 				/* ����������޶��ڤ�ξ�� */
290 				while (*p && *p != ',') {
291 					p = SkipSpace(p1 = SkipExpr(p, EXPR_SEMIMAX, SKIP_ELSE1));
292 				}
293 				if (*p == ',')
294 					p = SkipSpace(p+1);
295 			} else if (typ == MA_FSTRING) {
296 				p = p1 = StrEnd(p0);
297 			} else {
298 				p1 = SkipCommandArg(p0);
299 				p = SkipSpace(p1);
300 			}
301 			if (!*p && mfflag != M_FUNCTION && StrNthE(p0, p1-p0-1) == '{') {
302 				if (p1 - p0 != 1) {
303 					p = --p1;
304 					p1 = BackSkipSpace(p0, p1);
305 				} else {
306 					p = p0 = p1 = NULL;
307 					XFree((voidstar)nextbuf);
308 					bp = MakeBlockArg(&len, &nextbuf);
309 					if (typ == MA_FSTRING || typ == MA_AUTO) {
310 						argvb[argc].s = AEvalStringN(&len, bp, len);
311 						argvb[argc].len = len;
312 						argvb[argc].typ = MA_FBLOCK;
313 						XFree((voidstar)bp);
314 					} else {
315 						argvb[argc].s = bp;
316 						argvb[argc].len = len;
317 						argvb[argc].typ = MA_VBLOCK;
318 					}
319 					if (!nextbuf)
320 						break;
321 
322 					p = (const uchar *)nextbuf;
323 					continue;
324 				}
325 			} else if (mfflag == M_SYSCMD) {
326 				/* �ü�����ΰ����ξ��ϡ����ڡ������åȤ��ʤ� */
327 				p1 = p;
328 			}
329 			bp = DupStrN(p0, (len = p1 - p0));
330 			if (typ == MA_VERBATIM) {
331 				argvb[argc].s = bp;
332 				argvb[argc].len = len;
333 				argvb[argc].typ = MA_VERBATIM;
334 			} else if (typ == MA_EXPR || mfflag == M_FUNCTION ||
335 										typ == MA_AUTO && IsEvalArg(bp)) {
336 				argvb[argc].s = AEvalExprStr(&len, bp);
337 				argvb[argc].len = len;
338 				argvb[argc].typ = MA_EXPR;
339 				XFree((voidstar)bp);
340 			} else if (typ == MA_FSTRING) {
341 				argvb[argc].s = AEvalStringN(&len, bp, len);
342 				argvb[argc].len = len;
343 				argvb[argc].typ = MA_FSTRING;
344 				XFree((voidstar)bp);
345 			} else {
346 				argvb[argc].s = AReadString(&len, bp);
347 				argvb[argc].len = len;
348 				argvb[argc].typ = MA_QSTRING;
349 				XFree((voidstar)bp);
350 			}
351 		}
352 	}
353 
354 	if (maxargc >= 0 && argc > maxargc) {
355 #if UNIX
356 		ERROR_SS((const uchar *)(mfflag == M_FUNCTION ? "Too many arguments: %s(%s)"
357 														: "Too many arguments: %s %s"),
358 				 mname, argp);
359 #else
360 		Error((const uchar *)(mfflag == M_FUNCTION ? "Too many arguments: %s(%s)"
361 												   : "Too many arguments: %s %s"),
362 							mname, argp);
363 #endif
364 	} else if (p ? *SkipSpace(p)
365 				 : maxargc < 0 && StrNthE(argp, len-1) == '{') {
366 #if UNIX
367 		ERROR_SS("Invalid argument: %s %s", mname, argp);
368 #else
369 		Error("Invalid argument: %s %s", mname, argp);
370 #endif
371 	}
372 
373 	XFree((voidstar)nextbuf);
374 
375 	newargv = (marg_t*)XMalloc((argc+1) * sizeof(marg_t));
376 	memcpy(newargv, argvb, (argc+1) * sizeof(marg_t));
377 	*argcp = argc;
378 	return newargv;
379 }
380 
381 static void
FreeVarList(var_t * p)382 FreeVarList(var_t *p)
383 {
384 	var_t *p1;
385 
386 	while (p) {
387 		p1 = p;
388 		p = p->prev;
389 		XFree((voidstar)p1->name);
390 		XFree((voidstar)p1->val);
391 		XFree((voidstar)p1);
392 	}
393 }
394 
395 
396 /**************************************/
397 
398 #define ArgEqu(a, str)	((a).typ == MA_VERBATIM && \
399 									ArgEqu2((a).s, (str)))
400 static int
ArgEqu2(const uchar * p,const uchar * name)401 ArgEqu2(const uchar *p, const uchar *name)
402 {
403 	uchar s[128];
404 	CopyStr(s, p);
405 	RTrimSpace(s);
406 	return equ(s, name);
407 }
408 
409 #define ArgIsElse(a)	ArgEqu(a, "else")
410 #define ArgIsIf(a)		ArgEqu(a, "if")
411 
412 
413 static int
DoArgCommand(marg_t * arg,int restargs)414 DoArgCommand(marg_t *arg, int restargs)
415 {
416 	uchar *buf = (uchar *)XMalloc(evalbufsize);
417 	uchar *p = buf;
418 	int if_else_nest = 0;
419 	int argcnt = 0;
420 
421 	restargs++;
422 
423 	while (restargs > 0 && arg->typ == MA_VERBATIM) {
424 		if (ArgIsIf(*arg))
425 			if_else_nest++;
426 		else if (ArgIsElse(*arg)) {
427 			if (if_else_nest == 0)
428 				break;
429 			else
430 				--if_else_nest;
431 		}
432 
433 		p += CopyStrN(p, arg->s, arg->len);
434 		arg++;
435 		restargs--;
436 		argcnt++;
437 	}
438 	buf = (uchar *)XRealloc((voidstar)buf, (p - buf) + 1);
439 	Command(buf);
440 	XFree((voidstar)buf);
441 	return argcnt;
442 }
443 
444 static int
DoArg(marg_t * arg,int restargs)445 DoArg(marg_t *arg, int restargs)
446 {
447 	int argcnt;
448 
449 	break_level = B_NOBREAK;
450 
451 	if (arg->typ == MA_VBLOCK || arg->typ == MA_FBLOCK) {
452 		int solflag0 = solflag;
453 		int sol2flag0 = sol2flag;
454 
455 		solflag = sol2flag = TRUE;
456 		DoText(arg->s, arg->len);
457 
458 		solflag = solflag0;
459 		sol2flag = sol2flag0;
460 		return 1;
461 	} else if (arg->typ == MA_VERBATIM &&
462 				(argcnt = DoArgCommand(arg, restargs))) {
463 		return argcnt;
464 	} else {
465 		assert(FALSE);
466 		return 1;
467 	}
468 }
469 
470 /**************************************/
471 
472 /* break �ʤɤ�����г�¦�Υ֥�å������ȴ����褦�� */
473 #define BreakThrow()													\
474     do {																\
475 		if (break_level != B_NOBREAK && inmtextflag)					\
476 			sbufp = SBUFBTM;											\
477 	} while (0)
478 
479 #if UNIX
480 #define StatementErr(cmd, args)		ERROR_SS("Invalid statement: %s %s", cmd, args)
481 #else
482 #define StatementErr(cmd, args)		Error(f_StatementErr, cmd, args)
483 static uchar f_StatementErr[] = "Invalid statement: %s %s";
484 #endif
485 
486 static void
Cmd_if(const uchar * argp)487 Cmd_if(const uchar *argp)
488 /*
489  * if (<expr>) {<cmd>}* { else if (<expr>) {<cmd>}* }* [ else {<cmd>}* ]
490  */
491 {
492 	marg_t *argv;
493 	int argc;
494 	int i = 1;
495 	int cond = 0;
496 	int else_if_flag = FALSE;
497 
498 	argv = MakeMargv(&argc, argp, MA_VERBATIM, MAXMARGC, M_SYSCMD);
499 
500 	do {
501 		if (argc <= i || *argv[i].s != '(')
502 			StatementErr("if", argv[0].s);
503 		cond = EvalExprVal(argv[i].s, (const uchar **)NULL, EXPR_PRIM) != 0;
504 		i++;
505 
506 		while (i <= argc && !ArgIsElse(argv[i])) {
507 			if (cond)
508 				i += DoArg(&argv[i], argc-i);
509 			else
510 				i++;
511 			if (break_level != B_NOBREAK)
512 				goto _if_end;
513 		}
514 		if (!cond && i <= argc && (++i, ArgIsIf(argv[i]))) {
515 			/* else ��ľ�夬 if �ΤȤ� */
516 			else_if_flag = TRUE;
517 			i++;
518 		} else
519 			else_if_flag = FALSE;
520 	} while (else_if_flag);
521 
522 	/* else-part */
523 	if (!cond) {
524 		while (break_level == B_NOBREAK && i <= argc) {
525 			i += DoArg(&argv[i], argc-i);
526 		}
527 	}
528 _if_end:
529 	BreakThrow();
530 	FreeMargv(argc, argv);
531 }
532 
533 #define CheckNoArg(argp,name)											\
534     do {																\
535 		if (!(!*CutSpace(argp) || *(argp) == ';'))						\
536 			StatementErr(name, argp);									\
537 	} while (0)
538 
539 static void
Cmd_break(const uchar * argp)540 Cmd_break(const uchar *argp)
541 /*
542  * break
543  */
544 {
545 	CheckNoArg(argp, "break");
546 
547 	break_level = B_BREAK;			/* �롼�פ�λ���뤿��Υե饰���å� */
548 	if (inmtextflag)
549 		sbufp = SBUFBTM;			/* �֥�å��¹Ԥ���餻�� */
550 }
551 
552 static void
Cmd_continue(const uchar * argp)553 Cmd_continue(const uchar *argp)
554 /*
555  * continue
556  */
557 {
558 	CheckNoArg(argp, "continue");
559 
560 	break_level = B_CONTINUE;		/* �롼�פκǸ��ķ�֤���Υե饰���å� */
561 	if (inmtextflag)
562 		sbufp = SBUFBTM;			/* �֥�å��¹Ԥ���餻�� */
563 }
564 
565 
566 static void
Cmd_return(const uchar * argp)567 Cmd_return(const uchar *argp)
568 /*
569  * return  [ <expr> ]
570  */
571 {
572 	EvalReturnExpr(argp, EXPR_MAX);
573 	break_level = B_RETURN;
574 	if (inmtextflag)
575 		sbufp = SBUFBTM;			/* �֥�å��¹Ԥ���餻�� */
576 }
577 
578 
579 static void
Cmd_while_for_Sub(const uchar * argp,int is_for)580 Cmd_while_for_Sub(const uchar *argp, int is_for)
581 {
582 	marg_t *argv;
583 	int argc;
584 	int i = 0;
585 	const uchar *test_expr = NULL;
586 	const uchar *incr_expr = NULL;
587 
588 	argv = MakeMargv(&argc, argp, MA_VERBATIM, MAXMARGC, M_SYSCMD);
589 
590 	if (argc >= 1 && *argv[1].s == '(') {
591 		if (is_for) {
592 			const uchar *p = argv[1].s + 1;
593 			p = SkipExpr(p, EXPR_MAX, SKIP_NORMAL);
594 			if (*CutSpace(p) == ';') {
595 				p++;
596 				if (*CutSpace(p) != ';') {
597 					test_expr = p;
598 					p = SkipExpr(p, EXPR_MAX, SKIP_NORMAL);
599 					CutSpace(p);
600 				}
601 				if (*p == ';') {
602 					p++;
603 					if (*CutSpace(p) != ')') {
604 						incr_expr = p;
605 						p = SkipExpr(p, EXPR_MAX, SKIP_NORMAL);
606 						incr_expr = DupStrDiff(incr_expr, p);
607 						CutSpace(p);
608 					}
609 					if (*p == ')' && !*SkipSpace(p+1))
610 						i++;
611 				}
612 			}
613 		} else {
614 			test_expr = argv[1].s;
615 			i++;
616 		}
617 	}
618 	if (i == 0)
619 		StatementErr(is_for ? "for" : "while", argv[0].s);
620 
621 	break_level = B_NOBREAK;
622 
623 	if (is_for) {
624 		EvalExprVal(argv[1].s + 1, (const uchar **)NULL, EXPR_MAX);
625 	}
626 
627 	while ((break_level == B_NOBREAK || break_level == B_CONTINUE) &&
628 				(!test_expr || EvalExprVal(test_expr, (const uchar **)NULL,
629 								is_for ? EXPR_MAX : EXPR_PRIM) != 0)) {
630 		for (i = 2; i <= argc;) {
631 			i += DoArg(&argv[i], argc-i);
632 			if (break_level != B_NOBREAK)
633 				break;
634 		}
635 		if (incr_expr && (break_level==B_NOBREAK || break_level==B_CONTINUE)) {
636 			EvalExprVal(incr_expr, (const uchar **)NULL, EXPR_MAX);
637 		}
638 #if MSDOS || WINNT || __human68k__
639 		/* ̵�¥롼�פˤ������äƤ� ^C �����ߤ����ǤǤ���褦�� */
640 		(void)kbhit();
641 #endif
642 	}
643 
644 	if (break_level != B_RETURN)
645 		break_level = B_NOBREAK;
646 
647 	XFree((voidstar)incr_expr);
648 	FreeMargv(argc, argv);
649 }
650 
651 static void
Cmd_while(const uchar * argp)652 Cmd_while(const uchar *argp)
653 /*
654  * while <expr> {<cmd>}*
655  */
656 {
657 	Cmd_while_for_Sub(argp, 0);
658 }
659 
660 static void
Cmd_for(const uchar * argp)661 Cmd_for(const uchar *argp)
662 /*
663  * for (<expr>;<expr>;<expr>) {<cmd>}*
664  */
665 {
666 	Cmd_while_for_Sub(argp, 1);
667 }
668 
669 /**************************************/
670 
671 static void
BindArgs(const uchar * pvars)672 BindArgs(const uchar *pvars)
673 /*
674  * pvars: ['@'] {<var>}*
675  */
676 {
677 	int i;
678 	uchar *buf;
679 	uchar *p;
680 	uchar *name;
681 
682 	if (!pvars || !*pvars)
683 		return;
684 
685 	if (*pvars == '@') {
686 		i = 0;
687 		pvars++;
688 	} else {
689 		i = 1;
690 	}
691 	p = buf = DupStr(pvars);
692 	while (*p && i <= margc) {
693 		name = p;
694 		p = SkipKSym2(p);
695 		if (*p) *p++ = '\0';
696 		PutVar(name, margv[i].s, margv[i].len);
697 		i++;
698 		CutSpace(p);
699 	}
700 	XFree((voidstar)buf);
701 }
702 
703 
704 /**************************************/
705 
706 
707 #define NeedNewLocalVarEnv(mp)		((mp)->pvars==NULL || *((mp)->pvars)!='!')
708 
709 static void
CallMacro(macro_t * macp,const uchar * argp,int mfflag)710 CallMacro(macro_t *macp, const uchar *argp, int mfflag)
711 {
712 	marg_t *margv0 = margv;
713 	int margc0 = margc;
714 	marg_t *newmargv = NULL;
715 	int newmargc = 0;
716 	var_t *localvarlist0;
717 
718 	macname = macp->name;			/* ���顼ɽ���Ѥ�̾������ */
719 
720 	newmargv = MakeMargv(&newmargc, argp, macp->matyp, macp->maxargc, mfflag);
721 	margv = newmargv;
722 	margc = newmargc;
723 
724 	localvarlist0 = localvarlist;
725 
726 	if (NeedNewLocalVarEnv(macp)) {
727 		localvarlist = NULL;
728 		BindArgs(macp->pvars);
729 	}
730 
731 	ClearRetValue();
732 
733 	DoArg(&macp->body, 0);
734 
735 	if (NeedNewLocalVarEnv(macp)) {
736 		FreeVarList(localvarlist);
737 		localvarlist = localvarlist0;
738 	}
739 	FreeMargv(margc, margv);
740 	margv = margv0;
741 	margc = margc0;
742 	macname = NULL;
743 }
744 
745 /****************************** MacroCommand ******************************/
746 
747 int
MacroCommand(const uchar * cmd)748 MacroCommand(const uchar *cmd)
749 {
750 	const uchar *argp;
751 	uchar *p;
752 	macro_t *macp = NULL;
753 
754 	if (!IsKSym1Str(cmd))
755 		return FALSE;
756 
757 	argp = SkipKSym2(cmd);
758 
759 	if (IsFuncArgStr(argp))
760 		return FALSE;
761 
762 	p = DupStrDiff(cmd, argp);
763 	macp = GetMacro(p);
764 	XFree((voidstar)p);
765 
766 	if (macp) {
767 		if (IsSysCmdMacp(macp)) {
768 			/* �����ƥॳ�ޥ�� */
769 			macname = SysCmdName(macp);
770 			(SysCmdFnp(macp))(argp);
771 			macname = NULL;
772 		} else {
773 			CallMacro(macp, argp, M_COMMAND);
774 		}
775 		return TRUE;
776 	} else {
777 		/* �����Ǥʤ��ʤ� */
778 		return FALSE;
779 	}
780 }
781 
782 
783 /***************************** FuncMacroCall ******************************/
784 
785 int
FuncMacroCall(uchar * dst,macro_t * macp,const uchar * args)786 FuncMacroCall(uchar *dst, macro_t *macp, const uchar *args)
787 {
788 	assert(dst != NULL);
789 	assert(macp != NULL);
790 	assert(args != NULL);
791 
792 	if (IsSysCmdMacp(macp)) {
793 		/* �����ƥॳ�ޥ�ɤ�ؿ��Ȥ��ƸƤӽФ����Ȥϵ����ʤ� */
794 #if UNIX
795 		ERROR_SS("Illegal function: %s(%s)", SysCmdName(macp), args);
796 #else
797 		Error("Illegal function: %s(%s)", SysCmdName(macp), args);
798 #endif
799 	} else {
800 		CallMacro(macp, args, M_FUNCTION);
801 	}
802 	return CopyStrN(dst, retvalue.s, retvalue.len);
803 }
804 
805 /***************************** DefineCommand ******************************/
806 
807 static void
PutMacro(const uchar * name,const marg_t * body,matype_t matyp,int maxargc,const uchar * pvars)808 PutMacro(const uchar *name, const marg_t *body, matype_t matyp,
809 	 int maxargc, const uchar *pvars)
810 {
811 	macro_t  **pp;
812 	macro_t  *p;
813 
814 	assert(name != NULL);
815 
816 	pp = &macrolist;
817 	p = *pp;
818 	while (p) {
819 		if (equ(name, p->name)) {
820 			if (body) {
821 				/* �ͤ��դ��ؤ� */
822 				XFree((voidstar)p->body.s);
823 				XFree((voidstar)p->pvars);
824 				p->body.s = DupStrN(body->s, body->len);
825 				p->body.len = body->len;
826 				p->body.typ = body->typ;
827 				p->maxargc = maxargc;
828 				p->matyp = matyp;
829 				p->pvars = DupStr(pvars);
830 			} else {
831 				/* ��� */
832 				*pp = p->prev;
833 				XFree((voidstar)p->name);
834 				XFree((voidstar)p->body.s);
835 				XFree((voidstar)p->pvars);
836 				XFree((voidstar)p);
837 			}
838 			return;
839 		}
840 		pp = &p->prev;
841 		p = *pp;
842 	}
843 
844 	/* ̤����ʤ� */
845 	pp = &macrolist;
846 	if (body) {
847 		p = (macro_t *)XMalloc(sizeof(macro_t));
848 		p->name = DupStr(name);
849 		p->body.s = DupStrN(body->s, body->len);
850 		p->body.len = body->len;
851 		p->body.typ = body->typ;
852 		p->maxargc = maxargc;
853 		p->matyp = matyp;
854 		p->pvars = DupStr(pvars);
855 		p->prev = *pp;
856 		*pp = p;
857 	}
858 }
859 
860 
861 #if UNIX
862 #define DefErr()														\
863 	do {																\
864 		uchar *mbs = (uchar *)alloca(strlen((char *)src) * 2 + 1);		\
865 		sjis2mbstring((char *)mbs, (char *)src);						\
866 		Error("Invalid definition: ##%s", mbs);							\
867 	} while (0)
868 #else
869 #define DefErr()		Error(f_DefErr, src)
870 static uchar f_DefErr[] = "Invalid definition: ##%s";
871 #endif
872 
873 
874 void
DefineCommand(const uchar * src)875 DefineCommand(const uchar *src)
876 /*
877  * '##' <name>										-- ����κ��
878  * '##' <name> <def-body>							-- �����ʤ��ؿ����
879  * '##' <name> <param-list> <def-body>				-- �����դ��ؿ����
880  *
881  * <param-list>:
882  *  '(' ['!' | ':' | '&' | '^' | '#']
883  *      ['@' <var> [',']] {<var> [',']}* [<num> | '*'] ')'
884  */
885 {
886 	const uchar *argp;
887 	uchar *name;
888 	marg_t *argv;
889 	int argc;
890 	matype_t matyp = MA_NOARG;
891 	int maxargc = -1;
892 	marg_t *body = NULL;
893 	uchar *pvars = NULL;
894 
895 	CutSpace(src);
896 	if (!IsKSym1Str(src))
897 		DefErr();
898 
899 	argp = SkipKSym2(src);
900 	name = DupStrDiff(src, argp);
901 	CutSpace(argp);
902 
903 	argv = MakeMargv(&argc, argp, MA_VERBATIM, MAXMARGC, M_COMMAND);
904 
905 	if (argc < 0 || argc == 2 && *argv[1].s != '(' || argc > 2)
906 		DefErr();
907 
908 	if (argc == 0) {
909 		/* ����κ�� */
910 		body = NULL;
911 	} else if (argc == 1) {
912 		/* �����ʤ� */
913 		body = &argv[1];
914 		maxargc = 0;
915 	} else {
916 		/* �������� */
917 		uchar *dst = (uchar *)XMalloc(argv[1].len+1);
918 		uchar *dstp = dst;
919 		uchar *srcp = argv[1].s;
920 		uchar *sp1 = srcp;
921 		int varc = 0;
922 		int nobindflag = 0;
923 
924 		assert(*srcp == '(');
925 		srcp++;
926 		while (*CutSpace(srcp) != ')') {
927 			if (varc == 0 && *srcp == '@') {
928 				srcp = SkipSpace(srcp+1);
929 				if (IsKSym1Str(srcp)) {
930 					srcp = SkipKSym2(sp1 = srcp);
931 					*dstp++ = '@';
932 					dstp += CopyStrDiff(dstp, sp1, srcp);
933 					*dstp++ = ' ';
934 				}
935 			} else if (IsKSym1Str(srcp)) {
936 				varc++;
937 				srcp = SkipKSym2(sp1 = srcp);
938 				dstp += CopyStrDiff(dstp, sp1, srcp);
939 				*dstp++ = ' ';
940 			} else if (*srcp == '!') {
941 				nobindflag++;
942 				srcp++;
943 			} else if (*srcp == ':') {
944 				matyp = MA_VERBATIM;
945 				srcp++;
946 			} else if (*srcp == '&') {
947 				matyp = MA_FSTRING;
948 				srcp++;
949 			} else if (*srcp == '^') {
950 				matyp = MA_QSTRING;
951 				srcp++;
952 			} else if (*srcp == '#') {
953 				matyp = MA_EXPR;
954 				srcp++;
955 			} else if (*srcp == '*') {
956 				maxargc = MAXMARGC;
957 				srcp++;
958 			} else if (isdigit(*srcp)) {
959 				maxargc = RdNum(srcp, (const uchar **)&srcp);
960 			} else {
961 				DefErr();
962 			}
963 			if (*CutSpace(srcp) == ',')
964 				srcp++;
965 		}
966 		if (maxargc == -1 && varc)
967 			maxargc = varc;
968 
969 		if (matyp == MA_NOARG)
970 			matyp = MA_AUTO;
971 
972 		if (dstp > dst && *(dstp-1) == ' ')
973 			--dstp;
974 
975 		if (nobindflag) {
976 			if (dst != dstp)
977 				DefErr();
978 			*dstp++ = '!';					/* �ѿ�«���ʤ��ΰ� */
979 		}
980 
981 		*dstp = '\0';
982 		pvars = dst;
983 		body = &argv[2];
984 	}
985 	PutMacro(name, body, matyp, maxargc, pvars);
986 	XFree((voidstar)pvars);
987 	FreeMargv(argc, argv);
988 	XFree((voidstar)name);
989 }
990 
991 
992 /********************************* DoText *********************************/
993 
994 void
DoText(const uchar * src,int len)995 DoText(const uchar *src, int len)
996 {
997 	int inmtextflag0 = inmtextflag;
998 	uchar *sbufp0 = sbufp;
999 	uchar *sbufp2 = NULL;			/* �������ƥ����ȥХåե����Ƥ���¸ */
1000 	jmp_buf	errorjb0;
1001 
1002 	memcpy(errorjb0, errorjb, sizeof(jmp_buf));
1003 
1004 	if (setjmp(errorjb) == 0) {
1005 		if (sbufp != SBUFBTM) {
1006 			/* �������ƥ����ȥХåե������Ǥʤ���� */
1007 			sbufp2 = DupStrDiff(sbufp, SBUFBTM);	/* ���ԡ����ä� */
1008 			sbufp = SBUFBTM;						/* ���ꥢ���� */
1009 		}
1010 		UngetN(src, len);
1011 		inmtextflag = TRUE;
1012 		Trans1();
1013 
1014 		if (cc == EOF2)
1015 			cc = prevc;
1016 
1017 	} else {
1018 		/* ���顼��ķ��Ǥ����� */
1019 		break_level = B_RETURN;						/* �ޥ�����ȴ���� */
1020 	}
1021 	inmtextflag = inmtextflag0;
1022 
1023 	if (sbufp2) {
1024 		/* ���Υ������ƥ����ȥХåե����Ƥ���������Ƥ���ʤ� */
1025 		sbufp = sbufp0;
1026 		memcpy(sbufp, sbufp2, SBUFBTM - sbufp);		/* �������� */
1027 		XFree((voidstar)sbufp2);
1028 	}
1029 	/* ���Υ��顼�������᤹ */
1030 	memcpy(errorjb, errorjb0, sizeof(jmp_buf));
1031 }
1032 
1033 /*
1034  * Local variables:
1035  * mode: c
1036  * c-indent-level: 4
1037  * c-continued-statement-offset: 4
1038  * c-brace-offset: -4
1039  * c-argdecl-indent: 4
1040  * c-label-offset: -4
1041  * tab-width: 4
1042  * tab-stop-list: (4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80)
1043  * End:
1044  */
1045