OSDN Git Service

e05c4521c387ba75f6e57601c272638e78198337
[hmh/hhml.git] / wiki / wikicmd.cc
1 #include "wikicmd.h"
2 #include "wikitable.h"
3 #include "wikiformat.h"
4 #include "wikienv.h"
5 #include "wikimotor.h"
6 #include "ml-formvar.h"
7 #include "ml.h"
8 #include "expr.h"
9 #include "motorenv.h"
10 #include "motoroutput.h"
11 #include "util_const.h"
12 #include "util_check.h"
13 #include "util_string.h"
14 #include "ustring.h"
15 #include <boost/ptr_container/ptr_vector.hpp>
16 #include <assert.h>
17 #include <stdlib.h>
18
19 //#define  WIKIREPEATPROTECT    1
20 //#define  WIKIEVALPROTECT      1
21
22 /*
23 WIKICOMPAT: 1をセットすると,defun-wiki-commandで定義した関数の中で,motor-output, motor-output-rawで出力したテキストをWikiテキストとして解釈する。
24 */
25 /*DOC:
26 $premode:1
27 ==行コマンド==
28
29 */
30 /* ============================================================ */
31 static void  do_linevec (WikiLine::linevec* block, WikiFormat* wiki) {
32     if (block) {
33         WikiLineScanner  scanner (block);
34         wiki->compileLines (scanner);
35     }
36 }
37
38 /* ============================================================ */
39 /*DOC:
40 ===$repeat===
41  $repeat:''VAR'':''FROM'':''TO''[:''STEP'']
42  ...
43  $endrepeat
44 変数''VAR''に,数値''FROM''から''TO''までの値を1づつ加算しながら代入し,$endrepeatまでの間のブロックを繰り返し実行する。
45
46 */
47 //#WIKICMD      $repeat $endrepeat      wc_repeat
48 void  wc_repeat (WikiLine* wl, WikiFormat* wiki) {
49     WikiMotor  motor (wl->begin, wl->end, wiki);
50     WikiMotorObjVec  objv;
51     WikiMotorObjVecVec  args;
52     ustring  iv;
53     double  from = 0.;
54     double  to = 0.;
55     double  step = 1.;
56     double  i;
57     MNodePtr  h;
58
59 #ifdef WIKIREPEATPROTECT
60     if (wiki->protectMode && ! wl->fsuper) {
61 #ifdef DEBUG
62         std::cerr << "(wiki):(protected)\n";
63 #endif /* DEBUG */
64         return;
65     }
66 #endif
67
68 #ifdef DEBUG
69     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
70 #endif /* DEBUG */
71     motor.compile (objv);
72     objv.splitCharA (':', args);
73     if (args.size () == 3 || args.size () == 4) {
74         iv = clipWhite (args[0]->textOut (wiki));
75         from = strtod (args[1]->textOut (wiki));
76         to = strtod (args[2]->textOut (wiki));
77         if (args.size () == 4)
78             step = strtod (args[3]->textOut (wiki));
79     } else {
80         wiki->errorMsg.append (CharConst ("$repeat: wrong number of parameters.\n"));
81     }
82
83     if (step > 0.) {
84         for (i = from; i <= to; i += step) {
85             h = newMNode_num (i);
86             wiki->mlenv->setVar (iv, h ());
87             do_linevec (wl->block, wiki);
88 //          if (mlenv->qtimeup ())
89 //              break;
90         }
91     } else if (step < 0.) {
92         for (i = from; i >= to; i += step) {
93             h = newMNode_num (i);
94             wiki->mlenv->setVar (iv, h ());
95             do_linevec (wl->block, wiki);
96 //          if (wiki->mlenv->qtimeup ())
97 //              break;
98         }
99     }
100 }
101
102 /* ============================================================ */
103 /*DOC:
104 ===$doarray===
105  $doarray:''VAR1'',''VAR2'',...[:''INDEX_VAR'']
106  ...
107  $enddoarray
108
109 配列''VAR1'', ''VAR2'', ...の各要素をそれぞれ変数''VAR1'', ''VAR2'', ...に代入しながら,$enddoarrayまでのブロックを繰り返し実行する。
110 ブロックの中で変数''VAR1'', ...に代入した値は,配列に書き戻される。
111 配列の長さが異なる場合は,配列''VAR1''の長さに揃えられる。
112 ''INDEX_VAR''を指定すると,配列のインデックス番号を変数''INDEX_VAR''に代入して,ブロックを実行する。
113
114 */
115 //#WIKICMD      $doarray        $enddoarray     wc_doarray
116 void  wc_doarray (WikiLine* wl, WikiFormat* wiki) {
117     WikiMotor  motor (wl->begin, wl->end, wiki);
118     WikiMotorObjVec  objv;
119     WikiMotorObjVecVec  args;
120     std::vector<ustring>  lv;
121     ustring  iv;
122     int  i, n, iu, it;
123     MNodePtr  h;
124
125 #ifdef WIKIREPEATPROTECT
126     if (wiki->protectMode && ! wl->fsuper) {
127 #ifdef DEBUG
128         std::cerr << "(wiki):(protected)\n";
129 #endif /* DEBUG */
130         return;
131     }
132 #endif
133
134 #ifdef DEBUG
135     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
136 #endif /* DEBUG */
137     motor.compile (objv);
138     objv.splitCharA (':', args);
139     if (args.size () == 1 || args.size () == 2) {
140         WikiMotorObjVecVec  v;
141         args[0]->splitCharA (',', v);
142         for (int i = 0; i < v.size (); i ++)
143             lv.push_back (clipWhite (v[i]->textOut (wiki)));
144         if (args.size () == 2) {
145             iv = clipWhite (args[1]->textOut (wiki));
146         }
147     } else {
148         wiki->errorMsg.append (CharConst ("$repeat: wrong number of parameters.\n"));
149     }
150     iu = lv.size ();
151     if (iu > 0) {
152         n = wiki->mlenv->getArySize (lv[0]);
153         for (i = 1; i <= n; i ++) {
154             for (it = 0; it < iu; it ++) {
155                 wiki->mlenv->setVar (lv[it], wiki->mlenv->getAry (lv[it], i));
156             }
157             if (iv.size () > 0) {
158                 h = newMNode_num (i);
159                 wiki->mlenv->setVar (iv, h ());
160             }
161             do_linevec (wl->block, wiki);
162             for (it = 0; it < iu; it ++) {
163                 wiki->mlenv->setAry (lv[it], i, wiki->mlenv->getVar (lv[it]));
164             }
165         }
166         for (it = 0; it < iu; it ++) {
167             wiki->mlenv->setArySize (lv[it], n);
168         }
169     }
170 }
171
172 /* ============================================================ */
173 /*DOC:
174 ===$block===
175  $block:''EXPR''
176  ...
177  $elseblock:''EXPR''
178  ...
179  $elseblock
180  ...
181  $endblock
182
183 LISPセル''EXPR''が真のとき,$elseblockまたは$endblockまでのブロックを実行する。
184 $elseblockに条件を書かないとき,それ以前のすべての条件が真でないときに次のブロックを実行する。
185
186 */
187 //#WIKICMD      $block  $elseblock      $endblock       wc_block
188 void  wc_block (WikiLine* wl, WikiFormat* wiki) {
189     MotorSexp  ml (wiki->mlenv);
190     ustring  sexp (wl->begin, wl->end);
191     MNodePtr  v;
192     bool  q;
193
194 #ifdef WIKIEVALPROTECT
195     if (wiki->protectMode && ! wl->fsuper) {
196 #ifdef DEBUG
197         std::cerr << "(wiki):(protected)\n";
198 #endif /* DEBUG */
199         return;
200     }
201 #endif
202
203 #ifdef DEBUG
204     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
205 #endif /* DEBUG */
206     if (sexp.empty ()) {
207         q = true;
208     } else {
209         ml.scan (sexp);
210         if (ml.top.isCons ()) {
211             MNode*  arg = ml.top.cdr ();
212             if (arg && arg->isCons ()) {
213                 try {
214                     v = eval (arg->car (), wiki->mlenv);
215                 } catch (ustring& msg) {
216                     if (wiki->mlenv->currentCell ()) {
217                         wiki->errorMsg.append (wiki->mlenv->currentCell ()->dump_string_short ()).append (CharConst (": "));
218                     }
219                     wiki->errorMsg.append (msg).append (uLF);
220                 }
221             }
222             if (v ()) {
223                 q = v ()->to_bool ();
224             } else {
225                 q = false;
226             }
227         } else {
228             q = true;
229         }
230     }
231     if (q) {
232         do_linevec (wl->block, wiki);
233 #ifdef DEBUG
234         std::cerr << "(wiki):" << "$endblock" << "\n";
235 #endif /* DEBUG */
236     } else {
237         WikiLine*  w2 = wl->block2;
238         if (w2 && w2->fn) {
239             wl->fn (w2, wiki);
240         } else {
241 #ifdef DEBUG
242             std::cerr << "(wiki):" << "$endblock" << "\n";
243 #endif /* DEBUG */
244         }
245     }
246 }
247
248 /* ============================================================ */
249 //#WIKICMD      $setvar wc_setvar
250 void  wc_setvar (WikiLine* wl, WikiFormat* wiki) {
251     MotorSexp  ml (wiki->mlenv);
252     ustring  sexp (wl->begin, wl->end);
253     MNode*  arg;
254     ustring  var;
255     MNodePtr  v;
256
257 #if 0
258     if (wiki->protectMode && ! wl->fsuper) {
259 #ifdef DEBUG
260         std::cerr << "(wiki):(protected)\n";
261 #endif /* DEBUG */
262         return;
263     }
264 #endif
265
266 #ifdef DEBUG
267     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
268 #endif /* DEBUG */
269     if (! sexp.empty ()) {
270         ml.scan (sexp);
271         if (ml.top.isCons ()) {
272             arg = ml.top.cdr ();
273             if (arg && arg->isCons ()) {
274                 var = to_string (arg->car ());
275             }
276             nextNode (arg);
277             if (! arg) {
278                 wiki->errorMsg.append (CharConst ("$setvar: wrong number of parameters.\n"));
279                 return;
280             }
281             try {
282                 v = eval (arg->car (), wiki->mlenv);
283             } catch (ustring& msg) {
284                 if (wiki->mlenv->currentCell ()) {
285                     wiki->errorMsg.append (wiki->mlenv->currentCell ()->dump_string_short ()).append (CharConst (": "));
286                 }
287                 wiki->errorMsg.append (msg).append (uLF);
288             }
289         }
290         if (var.size () > 0) {
291             if (checkAry (var, var)) {
292                 wiki->mlenv->setAry (var, v ());
293             } else {
294                 wiki->mlenv->setVar (var, v ());
295             }
296         }
297     }
298 }
299
300 /* ============================================================ */
301 /*DOC:
302 ===$eval===
303  $eval:''EXPR''
304
305 LISPセル''EXPR''を実行する。
306
307 */
308 //#WIKICMD      $eval   wc_eval
309 void  wc_eval (WikiLine* wl, WikiFormat* wiki) {
310     MotorSexp  ml (wiki->mlenv);
311     ustring  sexp (wl->begin, wl->end);
312     MNodePtr  v;
313
314 #ifdef WIKIEVALPROTECT
315     if (wiki->protectMode && ! wl->fsuper) {
316 #ifdef DEBUG
317         std::cerr << "(wiki):(protected)\n";
318 #endif /* DEBUG */
319         return;
320     }
321 #endif
322
323 #ifdef DEBUG
324     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
325 #endif /* DEBUG */
326     if (! sexp.empty ()) {
327         ml.scan (sexp);
328         if (ml.top.isCons ()) {
329             MNode*  arg = ml.top.cdr ();
330             if (arg && arg->isCons ()) {
331                 try {
332                     v = eval (arg->car (), wiki->mlenv);
333                 } catch (ustring& msg) {
334                     if (wiki->mlenv->currentCell ()) {
335                         wiki->errorMsg.append (wiki->mlenv->currentCell ()->dump_string_short ()).append (CharConst (": "));
336                     }
337                     wiki->errorMsg.append (msg).append (uLF);
338                 }
339             }
340         }
341     }
342 }
343
344 /* ============================================================ */
345 /*DOC:
346 ===$evalblock===
347  $evalblock
348  ...
349  $endevalblock
350
351 ブロック内部に記述されたLISPファンクションを実行する。
352 実行できる関数は制限されている。
353
354 */
355 //#WIKICMD      $evalblock      $endevalblock   wc_evalblock
356 void  wc_evalblock (WikiLine* wl, WikiFormat* wiki) {
357     MotorSexp  ml (wiki->mlenv);
358 //    ustring  sexp (wl->begin, wl->end);
359
360 #ifdef WIKIEVALPROTECT
361     if (wiki->protectMode && ! wl->fsuper) {
362 #ifdef DEBUG
363         std::cerr << "(wiki):(protected)\n";
364 #endif /* DEBUG */
365         return;
366     }
367 #endif
368
369     if (wl->block) {
370         ustring  sexp (wl->end + 1, wl->block->back ().end + 1);
371 //      std::cerr << "[" << sexp << "]\n";
372 #ifdef DEBUG
373         std::cerr << "(wiki): $evalblock\n";
374 #endif /* DEBUG */
375         if (! sexp.empty ()) {
376             ml.scan (sexp);
377             MNode*  arg = &ml.top;
378             if (arg->isCons ()) {
379                 try {
380                     progn_ex (arg, wiki->mlenv);
381                 } catch (ustring& msg) {
382                     if (wiki->mlenv->currentCell ()) {
383                         wiki->errorMsg.append (wiki->mlenv->currentCell ()->dump_string_short ()).append (CharConst (": "));
384                     }
385                     wiki->errorMsg.append (msg).append (uLF);
386                 }
387             }
388         }
389     }
390 }
391
392 /* ============================================================ */
393 /*DOC:
394 ===$insert===
395  $insert:VARIABLE
396  $insert:VARIABLE:==
397  $insert:VARIABLE:superuser
398  $insert:VARIABLE:superuser:==
399
400 変数''VARIABLE''に格納されたWikiテキストを挿入する。
401 オプションの「=」を追加すると,「=」の数だけ挿入されるWikiテキストのタイトルの深さが下げられる。
402 superuserオプションをつけると,
403
404 */
405 //#WIKICMD      $insert wc_insert
406 void  wc_insert (WikiLine* wl, WikiFormat* wiki) {
407     WikiMotor  motor (wl->begin, wl->end, wiki);
408     WikiMotorObjVec  objv;
409     WikiMotorObjVecVec  argsv;
410     std::vector<ustring>  args;
411     int  hn;
412     bool  super = false;
413     bool  protect;
414     int  i;
415     static uregex  re_eq ("=+");
416     umatch  m;
417     
418 #ifdef DEBUG
419     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
420 #endif /* DEBUG */
421     motor.compile (objv);
422     objv.splitCharA (':', argsv);
423     for (i = 0; i < argsv.size (); i ++)
424         args.push_back (argsv[i]->textOut (wiki));
425
426     protect = wiki->protectMode && ! wl->fsuper;
427     hn = 0;
428     for (i = 1; i < args.size (); i ++) {
429         if (! protect && match (args[i], CharConst ("superuser"))) {
430             super = true;
431         } else if (usearch (args[i], m, re_eq)) {
432             hn = m[0].second - m[0].first;
433             if (hn < 0)
434                 hn = 0;
435             if (hn > 5)
436                 hn = 5;
437         } else {
438             // bad parameter
439         }
440     }
441     if (args.size () >= 1) {
442         AutoInclCount  autoIncl (wiki->mlenv);
443         ustring  text = wiki->getVar (args[0]);
444         WikiLine::linevec  bl;
445         wiki->headbase += hn;
446         wiki->pass1 (text, &bl, super);
447         autoIncl.inc ();
448         do_linevec (&bl, wiki);
449         wiki->headbase -= hn;
450     }
451 }
452
453 /* ============================================================ */
454 /*DOC:
455 ===$data===
456  $data:VARIABLE
457  ''TEXT...''
458  $enddata
459
460 */
461 static void  wldump (ustring& data, WikiLine::linevec* vwl);
462 static void  wldump (ustring& data, WikiLine* wl) {
463     data.append (wl->begin0, wl->end).append (uLF);
464     if (wl->block) {
465         wldump (data, wl->block);
466     }
467     if (wl->block2) {
468         wldump (data, wl->block2);
469     }
470 }
471
472 static void  wldump (ustring& data, WikiLine::linevec* vwl) {
473     int  i, n;
474
475     n = vwl->size ();
476     for (i = 0; i < n; i ++) {
477         wldump (data, &(*vwl)[i]);
478     }
479 }
480
481 //#WIKICMD      $data   $enddata        wc_data
482 void  wc_data (WikiLine* wl, WikiFormat* wiki) {
483     WikiMotor  motor (wl->begin, wl->end, wiki);
484     ustring  name;
485     ustring  data;
486     WikiMotorObjVec  objv;
487     WikiMotorObjVecVec  args;
488
489     if (wiki->protectMode && ! wl->fsuper) {
490 #ifdef DEBUG
491         std::cerr << "(wiki):(protected)\n";
492 #endif /* DEBUG */
493         return;
494     }
495
496     motor.compile (objv);
497     objv.splitCharA (':', args);
498     if (args.size () > 0) {
499         name = clipWhite (args[0]->textOut (wiki));
500     } else {
501         wiki->errorMsg.append (CharConst ("$data: missing variable name.\n"));
502         return;
503     }
504
505     if (wl->block) {
506         wldump (data, wl->block);
507         wiki->mlenv->setVar (name, newMNode_str (new ustring (data)));
508     }
509 }
510
511 /* ============================================================ */
512 /*DOC:
513 ===$local===
514  $local:''VARIABLE'',...
515  ...
516  $endlocal
517
518 */
519 //#WIKICMD      $local  $endlocal       wc_local
520 void  wc_local (WikiLine* wl, WikiFormat* wiki) {
521     WikiMotor  motor (wl->begin, wl->end, wiki);
522     WikiMotorObjVec  objv;
523     WikiMotorObjVecVec  args;
524     std::vector<ustring>  vars;
525     int  i, n;
526
527 #ifdef WIKIEVALPROTECT
528     if (wiki->protectMode && ! wl->fsuper) {
529 #ifdef DEBUG
530         std::cerr << "(wiki):(protected)\n";
531 #endif /* DEBUG */
532         return;
533     }
534 #endif
535
536 #ifdef DEBUG
537     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
538 #endif /* DEBUG */
539
540     motor.compile (objv);
541     objv.splitCharA (':', args);
542     if (args.size () == 1) {
543         WikiMotorObjVecVec  v;
544         args[0]->splitCharA (',', v);
545         for (i = 0; i < v.size (); i ++)
546             vars.push_back (clipWhite (v[i]->textOut (wiki)));
547     } else {
548         wiki->errorMsg.append (CharConst ("$local: wrong number of parameters.\n"));
549     }
550     n = vars.size ();
551     if (n > 0) {
552         AutoLocalVariable  autoLocal (wiki->mlenv);
553         for (i = 0; i < n; i ++) {
554             wiki->mlenv->setLocalVar (vars[i], NULL);
555         }
556         do_linevec (wl->block, wiki);
557 #ifdef DEBUG
558         std::cerr << "(endlocal)\n";
559 #endif /* DEBUG */
560     } else {
561         do_linevec (wl->block, wiki);
562     }
563 #ifdef DEBUG
564     std::cerr << "(wiki):$endlocal\n";
565 #endif /* DEBUG */
566 }
567
568 /* ============================================================ */
569 /*DOC:
570 ===$macro===
571  $macro:''NAME'':''VARIABLE'',...
572  ...
573  $endmacro
574
575  $NAME:PARAM,...
576 マクロは組み込みコマンドをオーバーライドできない。
577
578 */
579 //#WIKICMD      $macro  $endmacro       wc_macro
580 void  wc_macro (WikiLine* wl, WikiFormat* wiki) {
581     WikiMotor  motor (wl->begin, wl->end, wiki);
582     WikiMotorObjVec  objv;
583     WikiMotorObjVecVec  args;
584     ustring  name;
585 //    std::vector<ustring>  vars;
586     MNodeList  vars;
587     int  i, n;
588
589     assert (0); // メモリ管理問題
590
591     if (wiki->protectMode && ! wl->fsuper) {
592 #ifdef DEBUG
593         std::cerr << "(wiki):(protected)\n";
594 #endif /* DEBUG */
595         return;
596     }
597
598 #ifdef DEBUG
599     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
600 #endif /* DEBUG */
601
602     motor.compile (objv);
603     objv.splitCharA (':', args);
604     if (args.size () >= 1) {
605         name = clipWhite (args[0]->textOut (wiki));
606     } else {
607         wiki->errorMsg.append (CharConst ("$macro: wrong number of parameters.\n"));
608         return;
609     }
610     if (args.size () == 2) {
611         WikiMotorObjVecVec  v;
612         args[1]->splitCharA (',', v);
613         for (i = 0; i < v.size (); i ++) {
614 //          vars.push_back (clipWhite (v[i]->textOut (wiki)));
615             vars.append (newMNode_str (new ustring (clipWhite (v[i]->textOut (wiki)))));
616         }
617     } else if (args.size () > 2) {
618         wiki->errorMsg.append (CharConst ("$macro: wrong number of parameters.\n"));
619     }
620
621     if (wl->block) {
622         wiki->env->wikienv->wikiMacro.setVar (name, vars.release (), wl->block);
623         wl->block = NULL;
624     }
625
626 #ifdef DEBUG
627 //    std::cerr << "(wiki):$endmacro\n";
628 #endif /* DEBUG */
629 }
630
631 /* ============================================================ */
632 /*DOC:
633 ===$input-text, $input-textarea, $input-int, $input-real, $input-int-or-blank, $input-real-or-blank, $input-ascii, $input-bool===
634  $input-text:VARIABLE
635  $input-textarea:VARIABLE
636  $input-int:VARIABLE
637  $input-real:VARIABLE
638  $input-int-or-blank:VARIABLE
639  $input-real-or-blank:VARIABLE
640  $input-ascii:VARIABLE
641  $input-bool:VARIABLE
642
643 */
644 //#WIKICMD      $input-text     wc_input_text
645 //#WIKICMD      $input-textarea wc_input_textarea
646 //#WIKICMD      $input-int      wc_input_int
647 //#WIKICMD      $input-real     wc_input_real
648 //#WIKICMD      $input-int-or-blank     wc_input_int_or_blank
649 //#WIKICMD      $input-real-or-blank    wc_input_real_or_blank
650 //#WIKICMD      $input-ascii    wc_input_ascii
651 //#WIKICMD      $input-bool     wc_input_bool
652 static void  wc_input_sub (WikiLine* wl, WikiFormat* wiki, ustring (*prefn)(const ustring&), MNode* (FormVarOp::*postfn)(const ustring&)) {
653     WikiMotor  motor (wl->begin, wl->end, wiki);
654     WikiMotorObjVec  objv;
655     WikiMotorObjVecVec  args;
656
657 #ifdef DEBUG
658     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
659 #endif /* DEBUG */
660     motor.compile (objv);
661     objv.splitCharA (':', args);
662     ustring  name;
663     int  i;
664     FormVarOp  opt;
665
666     if (args.size () > 0) {
667         name = args[0]->textOut (wiki);
668         for (i = 1; i < args.size (); i ++) {
669             if (args[i]->matchHead (CharConst ("max="))) {
670                 ustring  x, y;
671                 args[i]->splitChar (wiki, '=', x, y);
672                 opt.max = to_uint32 (y);
673             } else if (args[i]->match (CharConst ("nowhite"))) {
674                 opt.nowhite = true;
675             } else if (args[i]->match (CharConst ("nw"))) {
676                 opt.nowhite = true;
677             } else if (args[i]->matchHead (CharConst ("filter="))) {
678                 ustring  x, y;
679                 args[i]->splitChar (wiki, '=', x, y);
680                 opt.filter = y;
681             } else if (args[i]->matchHead (CharConst ("default="))) {
682                 ustring  x, y;
683                 args[i]->splitChar (wiki, '=', x, y);
684                 opt.defaultVal = y;
685             } else {
686                 wiki->errorMsg.append (args[i]->textOut (wiki) + ustring (CharConst (": bad parameter.\n")));
687             }
688         }
689         opt.input (wiki->mlenv, name, prefn, postfn);
690     }
691 }
692
693 void  wc_input_text (WikiLine* wl, WikiFormat* wiki) {
694     wc_input_sub (wl, wiki, omitCtrl, &FormVarOp::stringNode);
695 }
696
697 void  wc_input_textarea (WikiLine* wl, WikiFormat* wiki) {
698     wc_input_sub (wl, wiki, omitCtrlX, &FormVarOp::stringNode);
699 }
700
701 void  wc_input_int (WikiLine* wl, WikiFormat* wiki) {
702     wc_input_sub (wl, wiki, NULL, &FormVarOp::intNode);
703 }
704
705 void  wc_input_real (WikiLine* wl, WikiFormat* wiki) {
706     wc_input_sub (wl, wiki, NULL, &FormVarOp::doubleNode);
707 }
708
709 void  wc_input_int_or_blank (WikiLine* wl, WikiFormat* wiki) {
710     wc_input_sub (wl, wiki, NULL, &FormVarOp::intBlankNode);
711 }
712
713 void  wc_input_real_or_blank (WikiLine* wl, WikiFormat* wiki) {
714     wc_input_sub (wl, wiki, NULL, &FormVarOp::doubleBlankNode);
715 }
716
717 void  wc_input_ascii (WikiLine* wl, WikiFormat* wiki) {
718     wc_input_sub (wl, wiki, omitNonAscii, &FormVarOp::stringNode);
719 }
720
721 void  wc_input_bool (WikiLine* wl, WikiFormat* wiki) {
722     wc_input_sub (wl, wiki, NULL, &FormVarOp::boolNode);
723 }
724
725 /* ============================================================ */
726 /*DOC:
727 ===$premode===
728  $premode:''BOOL''
729
730 フォーマット済みブロック内で,インラインファンクションの展開を行うモードの設定。
731 trueで展開を行う。
732
733 */
734 //#WIKICMD      $premode        wc_premode
735 void  wc_premode (WikiLine* wl, WikiFormat* wiki) {
736     WikiMotor  motor (wl->begin, wl->end, wiki);
737     WikiMotorObjVec  objv;
738     WikiMotorObjVecVec  argsv;
739     ustring  arg;
740
741 #ifdef DEBUG
742     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
743 #endif /* DEBUG */
744     motor.compile (objv);
745     objv.splitCharA (':', argsv);
746     if (argsv.size () > 0) {
747         arg = argsv[0]->textOut (wiki);
748     }
749     wiki->motorPre = to_bool (arg);
750 }
751
752 /* ============================================================ */
753 static void  call_defun_wikicmd (ustring& name, MNode* wf, WikiMotorObjVec& objv2, WikiLine* wl, WikiFormat* wiki) {
754     WikiMotorObjVecVec  argsv;
755     MNodePtr  vargs;
756
757     objv2.splitCharA (':', argsv);
758     vargs = wiki->buildArgs (argsv.begin (), argsv.end ());
759     {
760         MotorOutputString  out;
761         MotorOutput*  back = wiki->env->output;
762         WikiMotorOutputString*  wikiback = wiki->env->wikioutput;
763         WikiMotorOutputString  wikiout (wiki);
764         MNodePtr  node;
765         MNodePtr  bcell;
766
767         wiki->env->wikioutput = &wikiout;
768         wiki->env->output = &out;
769         bcell = wiki->env->mlenv->currentCell;
770         wiki->env->mlenv->currentCell = NULL;
771         try {
772             node = execDefun (wiki->env->mlenv, wf, vargs (), name);
773         } catch (ustring& msg) {
774             wiki->logLispFunctionError (msg, ustring (wl->begin, wl->end));
775         }
776         wiki->env->mlenv->currentCell = bcell;
777         if (wikiout.ans.length () > 0) {
778             WikiLine::linevec  bl;
779             wiki->pass1 (wikiout.ans, &bl, wl->fsuper);
780             do_linevec (&bl, wiki);
781         }
782         wiki->env->wikioutput = wikiback;
783         if (out.ans.length () > 0) {
784 #ifdef WIKICOMPAT
785             WikiLine::linevec  bl;
786             wiki->pass1 (out.ans, &bl, wl->fsuper);
787             do_linevec (&bl, wiki);
788 #else
789             wiki->pushBlockRaw (out.ans.begin (), out.ans.end ());
790 #endif
791         }
792         wiki->env->output = back;
793     }
794 }
795
796 static void  call_defun_macro (ustring& name, WikiMacro* mf, WikiMotorObjVec& objv2, WikiLine* wl, WikiFormat* wiki) {
797     WikiMotorObjVecVec  argsv;
798 //    MNodePtr  vargs;
799
800     objv2.splitCharA (':', argsv);
801 //    vargs = wiki->buildArgs (argsv.begin (), argsv.end ());
802 //    mf->mars;
803     {
804         AutoLocalVariable  autoLocal (wiki->mlenv);
805         MNode*  p = mf->vars ();
806         MNode*  t;
807         MNode*  v;
808         int  i, n;
809         n = argsv.size ();
810         i = 0;
811         while (p && (t = p->car ())) {
812             if (i < n) {
813                 v = newMNode_str (new ustring (argsv[i]->textOut (wiki)));
814                 i ++;
815             } else {
816                 v = NULL;
817             }
818             wiki->mlenv->setLocalVar (to_string (t), v);
819             p = p->cdr ();
820         }
821         do_linevec (mf->wl, wiki);
822     }
823 }
824
825 void  wc_call_defun (WikiLine* wl, WikiFormat* wiki) {
826     WikiMotor  motor (wl->begin + 1, wl->end, wiki);
827     WikiMotorObjVec  objv;
828     WikiMotorObjVec  objv2;
829     ustring  name;
830     MNode*  wf;
831     bool  fx = true;
832     WikiMacro*  mf;
833
834 #ifdef DEBUG
835     std::cerr << "(wiki):" << ustring (wl->begin0, wl->end) << "\n";
836 #endif /* DEBUG */
837     motor.compile (objv);
838     objv.splitChar_keyword (':', name, objv2);
839     if (wiki->protectMode && ! wl->fsuper && ! wiki->env->wikienv->wikiGuestFunc.get (name))
840         fx = false;
841
842     if (fx && (wf = wiki->env->wikienv->wikiCmd.getVar (name))) { // Wiki Command
843         call_defun_wikicmd (name, wf, objv2, wl, wiki);
844     } else if (mf = wiki->env->wikienv->wikiMacro.getVar (name)) { // Wiki Macro. macroは誰でも実行できる。
845 //      std::cerr << "macro:" << name << "\n";
846         call_defun_macro (name, mf, objv2, wl, wiki);
847     } else {                    // 処理なし
848         WikiLine::linevec  bl;
849         WikiLine*  wl2;
850         ustring  u (CharConst ("^"));
851
852         u.append (wl->begin, wl->end);
853         wl2 = new WikiLine (u.begin (), u.end (), wl->fsuper);
854         bl.push_back (wl2);
855         do_linevec (&bl, wiki);
856     }
857 }
858
859 void  wikiOutput (const ustring& text, bool fsuper, WikiFormat* wiki) {
860     WikiLine::linevec  bl;
861     wiki->pass1 (text, &bl, fsuper);
862     do_linevec (&bl, wiki);
863 }
864
865 /*DOC:
866 $premode:
867 */
868 /* ============================================================ */