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 = ¯olist;
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 = ¯olist;
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