5 #include "motoroutput.h"
6 #include "util_const.h"
7 #include "util_check.h"
8 #include "util_random.h"
9 #include "util_string.h"
10 #include "util_wsplitter.h"
16 #include <boost/ptr_container/ptr_vector.hpp>
26 (concat STRING...) -> STRING
27 パラメータの文字列を連結して一つの文字列を返す。
30 //#AFUNC concat ml_concat
32 MNode* ml_concat (MNode* cell, MlEnv* mlenv) {
33 MNode* arg = cell->cdr ();
34 AutoDelete<ustring> a1;
40 a1 ()->append (eval_str (arg->car (), mlenv));
43 return newMNode_str (a1.release ());
48 (megabyte NUMBER) -> STRING
51 //#AFUNC megabyte ml_megabyte
53 MNode* ml_megabyte (MNode* cell, MlEnv* mlenv) {
54 MNode* arg = cell->cdr ();
59 throw (uErrorWrongNumber);
61 val = eval_double (arg->car (), mlenv);
64 throw (uErrorWrongNumber);
68 return newMNode_str (new ustring (u));
70 val = floor (val / 1024. * 10.) / 10.;
73 u.append (CharConst ("K"));
74 return newMNode_str (new ustring (u));
76 val = floor (val / 1024. * 10. ) / 10.;
79 u.append (CharConst ("M"));
80 return newMNode_str (new ustring (u));
82 val = floor (val / 1024. * 10.) / 10.;
85 u.append (CharConst ("G"));
86 return newMNode_str (new ustring (u));
88 val = floor (val / 1024. * 10.) / 10.;
91 u.append (CharConst ("T"));
92 return newMNode_str (new ustring (u));
94 val = floor (val / 1024. * 10.) / 10.;
96 u.append (CharConst ("P"));
97 return newMNode_str (new ustring (u));
102 (c3 INTEGER) -> STRING
107 MNode* ml_c3 (MNode* cell, MlEnv* mlenv) {
108 MNode* arg = cell->cdr ();
112 throw (uErrorWrongNumber);
114 u = eval_str (arg->car (), mlenv);
117 throw (uErrorWrongNumber);
119 return newMNode_str (new ustring (c3 (u)));
124 (regexp-match REGEX TEXT [#i | :i BOOL]) -> BOOL
127 //#AFUNC regexp-match ml_regexp_match
128 //#WIKIFUNC regexp-match
129 MNode* ml_regexp_match (MNode* cell, MlEnv* mlenv) {
130 MNode* arg = cell->cdr ();
133 boost::wregex::flag_type f = boost::regex_constants::normal;
135 std::vector<MNode*> params;
136 std::vector<MNode*> keywords;
137 static paramList kwlist[] = {
138 {CharConst ("i"), true},
142 setParams (arg, 2, ¶ms, kwlist, &keywords, NULL);
143 reg = eval_str (params[0], mlenv);
144 text = eval_str (params[1], mlenv);
145 if (eval_bool (keywords[0], mlenv))
146 f |= boost::regex_constants::icase;
148 ans = wsearch_env (mlenv, text, reg, f);
150 return newMNode_bool (ans);
155 (match-string NUM) -> STRING
158 //#AFUNC match-string ml_match_string
159 //#WIKIFUNC match-string
160 MNode* ml_match_string (MNode* cell, MlEnv* mlenv) {
161 MNode* arg = cell->cdr ();
166 throw (uErrorWrongNumber);
167 n = eval_int (arg->car (), mlenv);
170 throw (uErrorWrongNumber);
172 if (0 <= n && n < mlenv->regmatch.size ()) {
173 ans = newMNode_str (new ustring (wtou (std::wstring (mlenv->regmatch[n].first, mlenv->regmatch[n].second))));
184 //#AFUNC prematch ml_prematch
186 MNode* ml_prematch (MNode* cell, MlEnv* mlenv) {
187 MNode* arg = cell->cdr ();
189 std::wstring::const_iterator b = mlenv->regtext.begin ();
192 throw (uErrorWrongNumber);
194 ans = newMNode_str (new ustring (wtou (std::wstring (b, mlenv->regmatch[0].first))));
201 (postmatch) -> STRING
204 //#AFUNC postmatch ml_postmatch
205 //#WIKIFUNC postmatch
206 MNode* ml_postmatch (MNode* cell, MlEnv* mlenv) {
207 MNode* arg = cell->cdr ();
209 std::wstring::const_iterator e = mlenv->regtext.end ();
212 throw (uErrorWrongNumber);
214 ans = newMNode_str (new ustring (wtou (std::wstring (mlenv->regmatch[0].second, e))));
221 (string-filter REGEX STRING [#i | :i BOOL] [:max NUM]) -> STRING
224 //#AFUNC string-filter ml_string_filter
225 //#WIKIFUNC string-filter
226 MNode* ml_string_filter (MNode* cell, MlEnv* mlenv) {
227 MNode* arg = cell->cdr ();
230 boost::wregex::flag_type f = boost::regex_constants::normal;
232 std::vector<MNode*> params;
233 std::vector<MNode*> keywords;
234 static paramList kwlist[] = {
235 {CharConst ("i"), true},
236 {CharConst ("max"), false},
240 setParams (arg, 2, ¶ms, kwlist, &keywords, NULL);
241 reg = eval_str (params[0], mlenv);
242 t = eval_str (params[1], mlenv);
243 if (eval_bool (keywords[0], mlenv))
244 f |= boost::regex_constants::icase;
245 if (eval_bool (keywords[1], mlenv)) {
246 max = eval_int (keywords[1], mlenv);
251 if (wsearch_env (mlenv, t, reg, f)) {
252 ustring ans = wtou (std::wstring (mlenv->regmatch[0].first, mlenv->regmatch[0].second));
254 substring (ans, 0, max, true, ans);
256 return newMNode_str (new ustring (ans));
258 return NULL; // unmatched
264 (regexp-replace REGEX TO_TEXT TEXT [#i | :i BOOL] [#g | #global | :g BOOL | :global BOOL]) -> TEXT
267 //#AFUNC regexp-replace ml_regexp_replace
268 //#WIKIFUNC regexp-replace
269 MNode* ml_regexp_replace (MNode* cell, MlEnv* mlenv) {
270 MNode* arg = cell->cdr ();
274 boost::wregex::flag_type f = boost::regex_constants::normal;
275 boost::match_flag_type mf = boost::regex_constants::match_default;
276 bool fglobal = false;
278 std::vector<MNode*> params;
279 std::vector<MNode*> keywords;
280 static paramList kwlist[] = {
281 {CharConst ("i"), true},
282 {CharConst ("g"), true},
283 {CharConst ("global"), true},
287 setParams (arg, 3, ¶ms, kwlist, &keywords, NULL);
288 reg = eval_str (params[0], mlenv);
289 to = eval_str (params[1], mlenv);
290 text = eval_str (params[2], mlenv);
291 if (eval_bool (keywords[0], mlenv))
292 f |= boost::regex_constants::icase;
293 if (eval_bool (keywords[1], mlenv))
295 if (eval_bool (keywords[2], mlenv))
299 mf |= boost::regex_constants::format_first_only;
300 ans = wreplace (text, reg, to, f, mf);
302 return newMNode_str (new ustring (ans));
307 (regexp-split REGEX STRING [#i | :i BOOL]) -> (PREMATCH_STRING POSTMATCH_STRING)
310 //#AFUNC regexp-split ml_regexp_split
311 //#WIKIFUNC regexp-split
312 MNode* ml_regexp_split (MNode* cell, MlEnv* mlenv) {
313 MNode* arg = cell->cdr ();
316 boost::wregex::flag_type f = boost::regex_constants::normal;
318 std::vector<MNode*> params;
319 std::vector<MNode*> keywords;
320 static paramList kwlist[] = {
321 {CharConst ("i"), true},
325 setParams (arg, 2, ¶ms, kwlist, &keywords, NULL);
326 reg = eval_str (params[0], mlenv);
327 text = eval_str (params[1], mlenv);
328 if (eval_bool (keywords[0], mlenv))
329 f |= boost::regex_constants::icase;
331 if (wsearch_env (mlenv, text, reg, f)) {
332 std::wstring::const_iterator b = mlenv->regtext.begin ();
333 std::wstring::const_iterator e = mlenv->regtext.end ();
334 ans.append (newMNode_str (new ustring (wtou (std::wstring (b, mlenv->regmatch[0].first)))));
335 ans.append (newMNode_str (new ustring (wtou (std::wstring (mlenv->regmatch[0].second, e)))));
337 ans.append (newMNode_str (new ustring (text)));
341 return ans.release ();
346 (split REGEX STRING) -> STRING_LIST
349 //#AFUNC split ml_split
351 MNode* ml_split (MNode* cell, MlEnv* mlenv) {
352 MNode* arg = cell->cdr ();
358 throw (uErrorWrongNumber);
360 reg = eval_str (arg->car (), mlenv);
361 nextNodeNonNil (arg);
362 t = eval_str (arg->car (), mlenv);
366 throw (uErrorWrongNumber);
369 std::wstring wt = utow (t);
370 std::wstring wreg = utow (reg);
371 boost::wregex wre (wreg);
372 WSplitter sp (wt, wre);
373 size_t m = wt.length () + 1;
376 ans.append (newMNode_str (new ustring (sp.cur ())));
379 throw (uErrorRegexp);
381 } catch (boost::regex_error& err) {
382 throw (uErrorRegexp);
384 return ans.release ();
389 (string-join TEXT [STRING | ARRAY | LIST]...) -> STRING
392 //#AFUNC string-join ml_string_join
393 //#WIKIFUNC string-join
394 MNode* ml_string_join (MNode* cell, MlEnv* mlenv) {
395 MNode* arg = cell->cdr ();
405 throw (uErrorWrongNumber);
407 sep = eval_str (arg->car (), mlenv);
408 nextNodeNonNil (arg);
411 val = eval (arg->car (), mlenv);
415 if (val ()->isSym ()) {
416 var = val ()->to_string ();
418 n = mlenv->getArySize (var);
419 for (i = 1; i <= n; i ++) {
424 v = mlenv->getAry (var, i);
426 ans.append (v->to_string ());
428 } else if (val ()->isCons ()) {
430 for (; a && a->isCons (); a = a->cdr ()) {
435 if (! isNil (a->car ()))
436 ans.append (a->car ()->to_string ());
439 var = val ()->to_string ();
448 return newMNode_str (new ustring (ans));
453 (password-match PASSWORD CRYPT) -> BOOL
456 //#AFUNC password-match ml_password_match
457 //#WIKIFUNC password-match
458 MNode* ml_password_match (MNode* cell, MlEnv* mlenv) {
459 MNode* arg = cell->cdr ();
464 throw (uErrorWrongNumber);
465 pass = eval_str (arg->car (), mlenv);
466 nextNodeNonNil (arg);
467 cpass = eval_str (arg->car (), mlenv);
470 throw (uErrorWrongNumber);
472 return newMNode_bool (passMatch (pass, cpass));
477 (password-crypt PASSWORD) -> STRING
480 //#AFUNC password-crypt ml_password_crypt
481 //#WIKIFUNC password-crypt
482 MNode* ml_password_crypt (MNode* cell, MlEnv* mlenv) {
483 MNode* arg = cell->cdr ();
487 throw (uErrorWrongNumber);
488 pass = eval_str (arg->car (), mlenv);
491 throw (uErrorWrongNumber);
493 return newMNode_str (new ustring (passCrypt (pass)));
498 (substring STR INDEX LENGTH) -> STRING
499 (substring STR INDEX) -> STRING
502 //#AFUNC substring ml_substring
503 //#WIKIFUNC substring
504 MNode* ml_substring (MNode* cell, MlEnv* mlenv) {
505 MNode* arg = cell->cdr ();
513 throw (uErrorWrongNumber);
514 str = eval_str (arg->car (), mlenv);
515 nextNodeNonNil (arg);
516 index = eval_int (arg->car (), mlenv);
520 length = eval_int (arg->car (), mlenv);
526 throw (uErrorWrongNumber);
528 substring (str, index, length, mode == 3, ans);
529 return newMNode_str (new ustring (ans));
534 (length STRING) -> NUMBER
537 //#AFUNC length ml_length
539 MNode* ml_length (MNode* cell, MlEnv* mlenv) {
540 MNode* arg = cell->cdr ();
545 throw (uErrorWrongNumber);
546 str = eval_str (arg->car (), mlenv);
549 throw (uErrorWrongNumber);
551 ans = strLength (str);
552 return newMNode_num (ans);
557 (pad0 NUMBER STRING) -> STRING
558 (pad0 NUMBER STRING_LIST) -> STRING_LIST
559 (pad0 NUMBER_LIST STRING_LIST) -> STRING_LIST
562 //#AFUNC pad0 ml_pad0
564 MNode* ml_pad0 (MNode* cell, MlEnv* mlenv) {
565 MNode* arg = cell->cdr ();
574 throw (uErrorWrongNumber);
575 num = np = eval (arg->car (), mlenv);
576 nextNodeNonNil (arg);
577 val = vp = eval (arg->car (), mlenv);
580 throw (uErrorWrongNumber);
588 n = to_int (np->car ());
594 ans.append (newMNode_str (new ustring (zeroPad (n, to_string (vp->car ())))));
596 if (vp && ! vp->isCons ())
599 return ans.release ();
603 n = to_int (np->car ());
607 return newMNode_str (new ustring (zeroPad (n, to_string (vp))));
616 (ellipsis NUM STRING) -> STRING
619 //#AFUNC ellipsis ml_ellipsis
621 MNode* ml_ellipsis (MNode* cell, MlEnv* mlenv) {
622 MNode* arg = cell->cdr ();
627 throw (uErrorWrongNumber);
628 num = eval_int (arg->car (), mlenv);
629 nextNodeNonNil (arg);
630 str = eval_str (arg->car (), mlenv);
633 throw (uErrorWrongNumber);
635 str = ellipsis (str, num);
636 return newMNode_str (new ustring (str));
641 (string-format FORMAT LIST-OF-ARGS) -> STRING
642 (string-format FORMAT ARGS...) -> STRING
644 |h:format|h:sample|h:note|
646 |${''NUM'':hex:''NUM''}|${1:hex:4}||
647 |${''NUM'':HEX:''NUM''}|${1:HEX:4}||
648 |${''NUM'':int:''NUM''}|${1:int:5}||
649 |${''NUM'':int:''NUM'':c}|${1:int:5:c}||
650 |${''NUM'':int:''NUM'':comma}|${1:int:5:comma}||
651 |${''NUM'':int:''NUM'':clip}|${1:int:5:clip}||
652 |${''NUM'':int:''NUM'':0}|${1:int:5:0}||
653 |${''NUM'':float:''NUM'':''NUM''}|${1:float:4:3}||
654 |${''NUM'':string:''NUM''}|${1:string:20}||
655 |${''NUM'':string:''NUM'':right}|${1:string:20:right}||
656 |${''NUM'':month}|${1:month}|Jan, Feb,...|
657 |${''NUM'':Month}|${1:Month}|January, February,...|
658 |${''NUM'':week}|${1:week}|Sun, Mon,...|
659 |${''NUM'':Week}|${1:Week}|Sunday, Monday,...|
662 //#AFUNC string-format ml_string_format
663 //#WIKIFUNC string-format
664 MNode* ml_string_format (MNode* cell, MlEnv* mlenv) {
665 MNode* arg = cell->cdr ();
667 boost::ptr_vector<MNodePtr> par;
671 throw (uErrorWrongNumber);
672 format = eval_str (arg->car (), mlenv);
675 a = eval (arg->car (), mlenv);
676 if (a && a->isCons ()) {
680 par.push_back (new MNodePtr);
681 par.back () = a->car ();
685 par.push_back (new MNodePtr);
691 return newMNode_str (new ustring (formatString (format, par)));
696 (random-key) -> STRING
699 //#AFUNC random-key ml_random_key
700 //#WIKIFUNC random-key
701 MNode* ml_random_key (MNode* cell, MlEnv* mlenv) {
702 MNode* arg = cell->cdr ();
705 throw (uErrorWrongNumber);
707 return newMNode_str (new ustring (randomKey ()));
711 ===date-format, gmdate-format===
712 (date-format FORMAT INTEGER) -> STRING
713 (gmdate-format FORMAT INTEGER) -> STRING
724 //#AFUNC date-format ml_date_format
725 //#WIKIFUNC date-format
726 MNode* ml_date_format (MNode* cell, MlEnv* mlenv) {
727 MNode* arg = cell->cdr ();
733 throw (uErrorWrongNumber);
734 format = eval_str (arg->car (), mlenv);
735 nextNodeNonNil (arg);
736 tm = eval_int (arg->car (), mlenv);
739 throw (uErrorWrongNumber);
741 localtime_r (&tm, &tmv);
742 return newMNode_str (new ustring (formatDateString (format, tmv)));
745 //#AFUNC gmdate-format ml_gmdate_format
746 //#WIKIFUNC gmdate-format
747 MNode* ml_gmdate_format (MNode* cell, MlEnv* mlenv) {
748 MNode* arg = cell->cdr ();
754 throw (uErrorWrongNumber);
755 format = eval_str (arg->car (), mlenv);
756 nextNodeNonNil (arg);
757 tm = eval_int (arg->car (), mlenv);
760 throw (uErrorWrongNumber);
762 gmtime_r (&tm, &tmv);
763 return newMNode_str (new ustring (formatDateString (format, tmv)));
768 (to-string OBJECT) -> STRING
771 //#AFUNC to-string ml_to_string
772 //#WIKIFUNC to-string
773 MNode* ml_to_string (MNode* cell, MlEnv* mlenv) {
774 MNode* arg = cell->cdr ();
778 throw (uErrorWrongNumber);
779 text = eval_str (arg->car (), mlenv);
782 throw (uErrorWrongNumber);
784 return newMNode_str (new ustring (text));
789 (dump-to-sexp OBJECT...) -> STRING
792 //#AFUNC dump-to-sexp ml_dump_to_sexp
793 //#WIKIFUNC dump-to-sexp
794 MNode* ml_dump_to_sexp (MNode* cell, MlEnv* mlenv) {
795 MNode* arg = cell->cdr ();
800 // text = eval_str (arg->car (), mlenv);
801 e = eval (arg->car (), mlenv);
803 if (text.length () > 0)
804 text.append (CharConst (" "));
805 text.append (dump_to_sexp (e ()));
807 return newMNode_str (new ustring (text));
812 // (to-sexp STRING) -> OBJECT
814 (read-sexp STRING) -> OBJECT
817 // //#AFUNC to-sexp ml_to_sexp
818 // //#WIKIFUNC to-sexp
819 //#AFUNC read-sexp ml_read_sexp
820 //#WIKIFUNC read-sexp
821 //MNode* ml_to_sexp (MNode* cell, MlEnv* mlenv) {
822 MNode* ml_read_sexp (MNode* cell, MlEnv* mlenv) {
823 MNode* arg = cell->cdr ();
828 throw (uErrorWrongNumber);
829 text = eval_str (arg->car (), mlenv);
832 throw (uErrorWrongNumber);
836 if (ml.top.isCons () && ml.top.cdr ()->isCons ())
837 return mlenv->retval = ml.top.cdr ()->car ();
844 (is-ascii63 STRING) -> BOOL
847 //#AFUNC is-ascii63 ml_is_ascii63
848 //#WIKIFUNC is-ascii63
849 MNode* ml_is_ascii63 (MNode* cell, MlEnv* mlenv) {
850 MNode* arg = cell->cdr ();
855 throw (uErrorWrongNumber);
856 text = eval_str (arg->car (), mlenv);
859 throw (uErrorWrongNumber);
861 ans = checkASCII (text);
863 return newMNode_bool (ans);
868 (sort-string LIST [#asc] [#desc]) -> LIST
871 //#AFUNC sort-string ml_sort_string
872 //#WIKIFUNC sort-string
873 MNode* ml_sort_string (MNode* cell, MlEnv* mlenv) {
874 MNode* arg = cell->cdr ();
878 std::vector<MNode*> list;
880 std::vector<MNode*> params;
881 std::vector<MNode*> keywords;
882 static paramList kwlist[] = {
883 {CharConst ("asc"), true},
884 {CharConst ("desc"), true},
888 setParams (arg, 1, ¶ms, kwlist, &keywords, NULL);
889 h = eval (params[0], mlenv);
890 if (eval_bool (keywords[0], mlenv))
892 if (eval_bool (keywords[1], mlenv))
898 if (a->car () && a->car ()->isStr ()) {
899 list.push_back (a->car ());
901 list.push_back (NULL);
910 int n = list.size ();
911 for (i = 1; i < n; i ++) {
927 else if (fdesc ^ (*list[k]->str >= *list[j]->str))
929 // swap (v[k], v[j]);
930 a = list[j]; list[j] = list[k]; list[k] = a;
934 for (; n > 0; n --) {
935 // swap (v[0], v[n - 1]);
936 a = list[n - 1]; list[n - 1] = list[0]; list[0] = a;
937 for (i = 1; i < n - 1; i ++) {
941 // if (! list[k] || ! list[j])
955 else if (fdesc ^ (*list[k]->str >= *list[j]->str))
957 // swap (v[k], v[j]);
958 a = list[j]; list[j] = list[k]; list[k] = a;
965 for (i = 0; i < n; i ++) {
966 ans.append (list[i]);
968 return ans.release ();
973 (to-upper STRING) -> STRING
976 //#AFUNC to-upper ml_to_upper
978 MNode* ml_to_upper (MNode* cell, MlEnv* mlenv) {
979 MNode* arg = cell->cdr ();
983 throw (uErrorWrongNumber);
984 text = eval_str (arg->car (), mlenv);
987 throw (uErrorWrongNumber);
989 return newMNode_str (new ustring (toUpper (text)));
994 (to-lower STRING) -> STRING
997 //#AFUNC to-lower ml_to_lower
999 MNode* ml_to_lower (MNode* cell, MlEnv* mlenv) {
1000 MNode* arg = cell->cdr ();
1004 throw (uErrorWrongNumber);
1005 text = eval_str (arg->car (), mlenv);
1008 throw (uErrorWrongNumber);
1010 return newMNode_str (new ustring (toLower (text)));