PageRenderTime 90ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/parser_lib.cpp

https://github.com/Morgulas/gccg-dev
C++ | 1682 lines | 1470 code | 125 blank | 87 comment | 129 complexity | 45cc202b71dca57c68980c4ee319ca4b MD5 | raw file
  1. /*
  2. Gccg - Generic collectible card game.
  3. Copyright (C) 2001,2002,2003,2004 Tommi Ronkainen
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program, in the file license.txt. If not, write
  14. to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. #include <ctype.h>
  18. #include <algorithm>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <time.h>
  22. #if !defined(__BCPLUSPLUS__) && !defined(_MSC_VER)
  23. # include <sys/time.h>
  24. # include <unistd.h>
  25. #endif
  26. #include <math.h>
  27. #include "parser.h"
  28. #include "parser_functions.h"
  29. #include "localization.h"
  30. #ifdef WIN32
  31. #include <windows.h>
  32. #undef max
  33. #undef min
  34. #endif
  35. using namespace std;
  36. //
  37. // Internal functions
  38. // ------------------
  39. namespace Evaluator
  40. {
  41. map<string,Data (*)(const Data& )> external_function;
  42. /// typeof(e) - Return the type of $e$ as a string {\tt null},
  43. /// {\tt integer}, {\tt string}, {\tt list} or {\tt real}.
  44. Data type_of(const Data& arg)
  45. {
  46. if(arg.IsInteger())
  47. return Data("integer");
  48. if(arg.IsString())
  49. return Data("string");
  50. if(arg.IsList())
  51. return Data("list");
  52. if(arg.IsReal())
  53. return Data("real");
  54. return Data("null");
  55. }
  56. /// print(e) - Print the value of expression $e$ to the standard
  57. /// output. List members are separeated by spaces.
  58. Data print(const Data& arg)
  59. {
  60. cout << arg << flush;
  61. return Data();
  62. }
  63. /// println(e) - Same as {\tt print}, but a new line is appended.
  64. Data println(const Data& arg)
  65. {
  66. cout << arg << endl << flush;
  67. return Data();
  68. }
  69. /// copy(e,n) - Create a list with element $e$ repeated $n$ times. If
  70. /// $n\le 0$, return empty list. Return {\tt NULL}, if arguments are invalid.
  71. Data copy(const Data& arg)
  72. {
  73. if(!arg.IsList(2) || !arg[1].IsInteger())
  74. return Null;
  75. Data ret;
  76. int n=arg[1].Integer();
  77. if(n <= 0)
  78. ret.MakeList(0);
  79. else
  80. {
  81. ret.MakeList(n);
  82. for(size_t i=0; i<ret.Size(); i++)
  83. ret[i]=arg[0];
  84. }
  85. return ret;
  86. }
  87. /// first(L) - If $L$ is a non-empty list, return the first element of
  88. /// the list. If it is a string, return the first character as a
  89. /// string. Otherwise {\tt NULL}.
  90. Data first(const Data& arg)
  91. {
  92. if(arg.IsList())
  93. {
  94. const Data& l=arg;
  95. if(l.Size())
  96. return l[0];
  97. }
  98. else if(arg.IsString())
  99. {
  100. string s=arg.String();
  101. if(s.length())
  102. return s.substr(0,1);
  103. else
  104. return string("");
  105. }
  106. else
  107. ArgumentError("first",arg);
  108. return Data();
  109. }
  110. /// last(L) - If $L$ is a non-empty list, return the last element of
  111. /// the list. If it is a string, return the last character as a a string.
  112. Data last(const Data& arg)
  113. {
  114. if(arg.IsList())
  115. {
  116. const Data& l=arg;
  117. if(l.Size())
  118. return l[l.Size()-1];
  119. }
  120. else if(arg.IsString())
  121. {
  122. string s=arg.String();
  123. if(s.length())
  124. return s.substr(s.length()-1,1);
  125. else
  126. return string("");
  127. }
  128. else
  129. ArgumentError("last",arg);
  130. return Data();
  131. }
  132. /// random(n) - Return random number between $0$ and $n-1$. If $n$
  133. /// is not an integer, return {\tt NULL}.
  134. Data random(const Data& arg)
  135. {
  136. if(arg.IsList())
  137. {
  138. const Data& l=arg;
  139. if(l.Size())
  140. return l[better_rand(l.Size())];
  141. }
  142. else if(arg.IsInteger())
  143. {
  144. return better_rand(arg.Integer());
  145. }
  146. else
  147. ArgumentError("random",arg);
  148. return Data();
  149. }
  150. /// randomize(e) - Initialize random number generator with seed
  151. /// $e$ if $e$ is integer. Otherwise initialze it with microsecond
  152. /// time value taken from system clock. Return value is the seed.
  153. Data randomize(const Data& arg)
  154. {
  155. int seed;
  156. if(arg.IsInteger())
  157. seed=arg.Integer();
  158. else
  159. {
  160. #if defined(WIN32) || defined(__WIN32__)
  161. seed=(int)clock();
  162. #else
  163. timeval t;
  164. gettimeofday(&t,0);
  165. seed=t.tv_usec;
  166. #endif
  167. }
  168. srand((unsigned) seed);
  169. return Data(seed);
  170. }
  171. /// shuffle(L) - Return a randomly shuffled version of list $L$.
  172. Data shuffle(const Data& arg)
  173. {
  174. if(arg.IsList())
  175. {
  176. Data ret;
  177. ret.MakeList(arg.Size());
  178. for(size_t i=0; i<arg.Size(); i++)
  179. ret[i]=arg[i];
  180. if(ret.Size() > 1)
  181. {
  182. for(size_t i=0; i<ret.Size(); i++)
  183. swap(ret[i],ret[i + better_rand(ret.Size() - i)]);
  184. }
  185. return ret;
  186. }
  187. else
  188. ArgumentError("shuffle",arg);
  189. return Data();
  190. }
  191. /// tail(L) - Return all members of the list $L$ except the
  192. /// first. If $L$ have one or zero members, return empty list. If
  193. /// $L$ is not a list, return {\tt NULL}.
  194. Data tail(const Data& arg)
  195. {
  196. Data ret;
  197. if(arg.IsList())
  198. {
  199. const Data& l=arg;
  200. if(l.Size() <= 1)
  201. {
  202. ret.MakeList();
  203. }
  204. else
  205. {
  206. ret.MakeList(l.Size()-1);
  207. for(size_t i=0; i<l.Size()-1; i++)
  208. ret[i]=l[i+1];
  209. }
  210. }
  211. else
  212. return Null;
  213. return ret;
  214. }
  215. /// head(L) - Return all member of the list $L$ except the
  216. /// last. If $L$ have one or zero members, return empty list. If
  217. /// $L$ is not a list, return {\tt NULL}.
  218. Data head(const Data& arg)
  219. {
  220. Data ret;
  221. if(arg.IsList())
  222. {
  223. const Data& l=arg;
  224. if(l.Size() <= 1)
  225. {
  226. ret.MakeList();
  227. }
  228. else
  229. {
  230. ret.MakeList(l.Size()-1);
  231. for(size_t i=0; i<l.Size()-1; i++)
  232. ret[i]=l[i];
  233. }
  234. }
  235. else
  236. return Null;
  237. return ret;
  238. }
  239. /// index(L_1,L_2) - Select members of list $L_1$ using list $L_2$
  240. /// as index. If any member $i$ of $L_2$ is not integer or $i < 0$
  241. /// or $i \ge |L_1|$, error is thrown. The resulting list has the
  242. /// same number of elements as $L_2$, each element corresponding
  243. /// to indexing member in $L_2$.
  244. Data index(const Data& arg)
  245. {
  246. Data ret;
  247. if(!arg.IsList(2) || !arg[0].IsList() || !arg[1].IsList())
  248. ArgumentError("index",arg);
  249. ret.MakeList();
  250. const Data &k1=arg[0];
  251. for(size_t i=0; i<arg[1].Size(); i++)
  252. {
  253. const Data &k2=arg[1][i];
  254. if(!k2.IsInteger())
  255. throw LangErr("index(const Data& )","Bad index "+tostr(k2).String());
  256. size_t n=k2.Integer();
  257. if(n >= k1.Size())
  258. throw LangErr("index(const Data& )","Index "+tostr(k2).String()+" out of range");
  259. ret.AddList(k1[n]);
  260. }
  261. return ret;
  262. }
  263. /// tostr(e) - Convert any element to string. This string is in
  264. /// such format that it produces element $e$ when evaluated.
  265. Data tostr(const Data& arg)
  266. {
  267. if(arg.IsString())
  268. {
  269. const string& s=arg.String();
  270. string ret;
  271. for(size_t i=0; i<s.length(); i++)
  272. {
  273. if(s[i]=='\\')
  274. ret+="\\\\";
  275. else if(s[i]=='\n')
  276. ret+="\\n";
  277. else if(s[i]=='"')
  278. ret+="\\\"";
  279. else
  280. ret+=s[i];
  281. }
  282. return Data("\""+ret+"\"");
  283. }
  284. if(arg.IsNull())
  285. return Data("NULL");
  286. if(arg.IsReal())
  287. {
  288. static char parser_buffer[128];
  289. #ifdef WIN32
  290. sprintf(parser_buffer,"%.10f",arg.Real());
  291. #else
  292. snprintf(parser_buffer,127,"%.10f",arg.Real());
  293. #endif
  294. return Data(parser_buffer);
  295. }
  296. if(arg.IsInteger())
  297. return Data(ToString(arg.Integer()));
  298. if(arg.IsList())
  299. {
  300. string s="(";
  301. const Data& L=arg;
  302. Data elem;
  303. for(size_t i=0; i<L.Size(); i++)
  304. {
  305. if(i)
  306. s+=",";
  307. s+=tostr(L[i]).String();
  308. }
  309. if(L.Size() <= 1)
  310. s+=",";
  311. s+=")";
  312. return s;
  313. }
  314. return Data();
  315. }
  316. /// seq(n_1,n_2) - Generate sequence $(n_1,n_1+1,...,n_2)$. Return
  317. /// {\tt NULL} if $n_1 > n_2$ or if arguments are not integers.
  318. Data seq(const Data& arg)
  319. {
  320. if(!arg.IsList(2) || !arg[0].IsInteger() || !arg[0].IsInteger())
  321. ArgumentError("seq",arg);
  322. int n1=arg[0].Integer();
  323. int n2=arg[1].Integer();
  324. if(n1 > n2)
  325. return Data();
  326. Data ret;
  327. ret.MakeList(size_t(n2-n1+1));
  328. for(int i=n1; i<=n2; i++)
  329. ret[i-n1]=i;
  330. return ret;
  331. }
  332. /// array(d_1,...,d_n) - This function creates list of lists
  333. /// structure which is suitable for array like indexing. Dimension
  334. /// of the array is $n$ and each $d_i$ denotes the size of the
  335. /// $i$th dimension of the array. Initial values of the list are
  336. /// {\tt NULL}.
  337. Data array(const Data& arg)
  338. {
  339. Data ret;
  340. if(arg.IsInteger())
  341. {
  342. int sz=arg.Integer();
  343. if(sz<=0)
  344. throw LangErr("array(const Data& )","Bad dimension "+tostr(arg).String());
  345. ret.MakeList(sz);
  346. return ret;
  347. }
  348. if(arg.IsList())
  349. {
  350. const Data& dim=arg;
  351. if(dim.Size()==0)
  352. ArgumentError("array",arg);
  353. Data a;
  354. for(int i=dim.Size()-1; i>=0; i--)
  355. {
  356. if(dim[i].Integer() <= 0)
  357. ArgumentError("array",arg);
  358. ret.MakeList(dim[i].Integer(),a);
  359. a=ret;
  360. }
  361. }
  362. else
  363. ArgumentError("array",arg);
  364. return ret;
  365. }
  366. /// length(e) - If $e$ is a string or a list, return length of
  367. /// it. Otherwise return -1.
  368. Data length(const Data& arg)
  369. {
  370. if(arg.IsList())
  371. return int(arg.Size());
  372. else if(arg.IsString())
  373. return int(arg.String().length());
  374. return -1;
  375. }
  376. /// substr(s,p,z) - Return substring of $s$ starting at position
  377. /// $p$ and having a length of $z$. If $z$ is not given, return
  378. /// substring of $s$ starting at position $p$ until end of the
  379. /// string.
  380. Data substr(const Data& arg)
  381. {
  382. string str;
  383. int pos=0;
  384. int size=0;
  385. if(arg.IsList(2))
  386. {
  387. if(!arg[0].IsString() || !arg[1].IsInteger())
  388. ArgumentError("substr",arg);
  389. str=arg[0].String();
  390. pos=arg[1].Integer();
  391. size=str.length();
  392. }
  393. else if(arg.IsList(3))
  394. {
  395. if(!arg[0].IsString() || !arg[1].IsInteger() || !arg[2].IsInteger())
  396. ArgumentError("substr",arg);
  397. str=arg[0].String();
  398. pos=arg[1].Integer();
  399. size=arg[2].Integer();
  400. }
  401. else
  402. ArgumentError("substr",arg);
  403. if(pos < 0 || size < 0)
  404. ArgumentError("substr",arg);
  405. if(size_t(pos) > str.length())
  406. return string();
  407. return str.substr(pos,size);
  408. }
  409. /// sort(L) - Return list as sorted according to {\tt <}
  410. /// operator.
  411. Data sort(const Data& arg)
  412. {
  413. if(!arg.IsList())
  414. ArgumentError("sort",arg);
  415. Data ret=arg;
  416. ret.Sort();
  417. return ret;
  418. }
  419. /// flatten(L) - If $L$ is not a list, return a list containing
  420. /// $L$ as an element. Otherwise destroy sublist structures and
  421. /// leave elements untouched.
  422. Data flatten(const Data& arg)
  423. {
  424. bool reflatten=false;
  425. Data ret;
  426. ret.MakeList();
  427. if(!arg.IsList())
  428. ret.AddList(arg);
  429. else
  430. {
  431. for(size_t i=0; i<arg.Size(); i++)
  432. {
  433. if(arg[i].IsList())
  434. {
  435. const Data& sublist=arg[i];
  436. for(size_t j=0; j<sublist.Size(); j++)
  437. {
  438. ret.AddList(sublist[j]);
  439. if(sublist[j].IsList())
  440. reflatten=true;
  441. }
  442. }
  443. else
  444. ret.AddList(arg[i]);
  445. }
  446. }
  447. if(reflatten)
  448. return flatten(ret);
  449. return ret;
  450. }
  451. /// quit(n) - Throw Quit exception with optional exit code $n$.
  452. Data quit(const Data& arg)
  453. {
  454. if(!arg.IsNull() && !arg.IsInteger())
  455. ArgumentError("quit",arg);
  456. if(arg.IsInteger())
  457. throw Error::Quit(arg.Integer());
  458. throw Error::Quit();
  459. }
  460. /// count(e,L) - Count number of elements $e$ in list $L$.
  461. Data count(const Data& arg)
  462. {
  463. if(!arg.IsList(2) || !arg[1].IsList())
  464. ArgumentError("count",arg);
  465. const Data& L=arg[1];
  466. const Data& e=arg[0];
  467. int n=0;
  468. for(int i=L.Size()-1; i>=0; i--)
  469. {
  470. if(e==L[i])
  471. n++;
  472. }
  473. return n;
  474. }
  475. /// reverse(L) - Return a list $L$ reversed or throw an exception
  476. /// if $L$ is not a list.
  477. Data reverse(const Data& arg)
  478. {
  479. if(!arg.IsList())
  480. ArgumentError("reverse",arg);
  481. Data ret;
  482. ret.MakeList(arg.Size());
  483. for(int j=0,i=arg.Size()-1; i >= 0; i--,j++)
  484. ret[j]=arg[i];
  485. return ret;
  486. }
  487. /// has_entry(e,L) - Return 1 if dictionary $L$ has member $e$, 0
  488. /// otherwise. Throw exception, if $L$ is not a dictionary.
  489. Data has_entry(const Data& arg)
  490. {
  491. if(!arg.IsList(2) || !arg[1].IsList())
  492. ArgumentError("has_entry",arg);
  493. const Data& L=arg[1];
  494. int n=L.Size();
  495. const Data& search=arg[0];
  496. for(int i=0; i<n; i++)
  497. if(!L[i].IsList(2))
  498. throw LangErr("has_entry","invalid dictionary entry "+tostr(L[i]).String()+" in dictionary "+tostr(L).String());
  499. else if(L[i][0]==search)
  500. return 1;
  501. return 0;
  502. }
  503. /// max(L) - Return maximum member of the list $L$ with respect to
  504. /// < operator.
  505. Data max(const Data& arg)
  506. {
  507. if(!arg.IsList())
  508. ArgumentError("max",arg);
  509. const Data& L=arg;
  510. if(L.Size()==0)
  511. return Null;
  512. Data n;
  513. for(size_t i=0; i<L.Size(); i++)
  514. if(i==0 || L[i] > n)
  515. n=L[i];
  516. return n;
  517. }
  518. /// min(L) - Return minimum member of the list $L$ with respect to
  519. /// < operator.
  520. Data min(const Data& arg)
  521. {
  522. if(!arg.IsList())
  523. ArgumentError("min",arg);
  524. const Data& L=arg;
  525. if(L.Size()==0)
  526. return Null;
  527. Data n;
  528. for(size_t i=0; i<L.Size(); i++)
  529. if(i==0 || L[i] < n)
  530. n=L[i];
  531. return n;
  532. }
  533. /// left(s,n) - Return $n$ characters from the beginning of string
  534. /// $s$ or empty string if $n \le 0$. If $s$ is a list, then
  535. /// return $n$ members from the beginning of the list.
  536. Data left(const Data& arg)
  537. {
  538. if(!arg.IsList(2) || !(arg[0].IsString() || arg[0].IsList()) ||!arg[1].IsInteger())
  539. ArgumentError("left",arg);
  540. int n=arg[1].Integer();
  541. if(arg[0].IsString())
  542. {
  543. const string& s=arg[0].String();
  544. if(n <= 0)
  545. return string("");
  546. if(size_t(n) >= s.length())
  547. return s;
  548. return s.substr(0,n);
  549. }
  550. const Data& L=arg[0];
  551. if(n < 0)
  552. n=0;
  553. if((size_t)n > L.Size())
  554. n=L.Size();
  555. Data ret;
  556. ret.MakeList(n);
  557. for(size_t i=0; i<(size_t)n; i++)
  558. ret[i]=L[i];
  559. return ret;
  560. }
  561. /// right(s,n) - Return $n$ characters from the end of string $s$
  562. /// or empty string if $n \le 0$. If $s$ is a list, then return
  563. /// $n$ members from the end of the list.
  564. Data right(const Data& arg)
  565. {
  566. if(!arg.IsList(2) || !(arg[0].IsString() || arg[0].IsList()) ||!arg[1].IsInteger())
  567. ArgumentError("right",arg);
  568. int n=arg[1].Integer();
  569. if(arg[0].IsString())
  570. {
  571. const string& s=arg[0].String();
  572. if(n <= 0)
  573. return string("");
  574. if(size_t(n) >= s.length())
  575. return s;
  576. return s.substr(s.length()-n,n);
  577. }
  578. const Data& L=arg[0];
  579. if(n < 0)
  580. n=0;
  581. if((size_t)n > L.Size())
  582. n=L.Size();
  583. Data ret;
  584. ret.MakeList(n);
  585. for(size_t i=0,j=L.Size()-n; i<(size_t)n; i++,j++)
  586. ret[i]=L[j];
  587. return ret;
  588. }
  589. Data ReadLiteral(const char*& src)
  590. {
  591. while(*src && isspace(*src))
  592. src++;
  593. if(CheckFor("NULL",src))
  594. {
  595. return Null;
  596. }
  597. if(*src=='"' || *src=='\'')
  598. {
  599. string ret;
  600. ReadString(src,ret);
  601. return ret;
  602. }
  603. bool neg=false;
  604. bool dbl=false;
  605. if(*src=='-')
  606. {
  607. src++;
  608. neg=true;
  609. }
  610. if(*src >= '0' && *src <= '9')
  611. {
  612. const char* num;
  613. num=src;
  614. while((*src>='0' && *src<='9') || *src=='.')
  615. {
  616. if(*src=='.')
  617. dbl=true;
  618. src++;
  619. }
  620. if(dbl)
  621. {
  622. double ret;
  623. if(neg)
  624. ret=-1.0*atof(num);
  625. else
  626. ret=atof(num);
  627. return ret;
  628. }
  629. else
  630. {
  631. int ret;
  632. if(neg)
  633. ret = -1 * atoi(num);
  634. else
  635. ret = atoi(num);
  636. return ret;
  637. }
  638. }
  639. if(*src=='(')
  640. {
  641. Data ret;
  642. ret.MakeList();
  643. while(*src && isspace(*src))
  644. src++;
  645. if(CheckFor("(,)",src))
  646. return ret;
  647. src++;
  648. ret.AddList(ReadLiteral(src));
  649. while(*src && isspace(*src))
  650. src++;
  651. if(CheckFor(",)",src))
  652. return ret;
  653. again:
  654. while(*src && isspace(*src))
  655. src++;
  656. if(*src!=',')
  657. throw LangErr("ReadLiteral","missing , in "+string(src)+"'");
  658. src++;
  659. while(*src && isspace(*src))
  660. src++;
  661. if(*src==')')
  662. {
  663. src++;
  664. return ret;
  665. }
  666. ret.AddList(ReadLiteral(src));
  667. while(*src && isspace(*src))
  668. src++;
  669. if(*src==')')
  670. {
  671. src++;
  672. return ret;
  673. }
  674. goto again;
  675. }
  676. throw LangErr("ReadLiteral","invalid string: '"+string(src)+"'");
  677. }
  678. /// toval(e) - Convert string converted by {\tt tostr} back to
  679. /// appropriate value. If $e$ is not a string, return $e$.
  680. Data toval(const Data& arg)
  681. {
  682. if(!arg.IsString())
  683. return arg;
  684. string s=arg.String();
  685. const char *src=s.c_str();
  686. Data ret=ReadLiteral(src);
  687. while(*src && isspace(*src))
  688. src++;
  689. if(*src!=0)
  690. ArgumentError("toval",arg);
  691. return ret;
  692. }
  693. /// values(D) - Return list of value elements of dictionary $D$ or
  694. /// throw error if $D$ is not a dictionary. This functions also
  695. /// returns list of first elements of list containing only pairs.
  696. Data values(const Data& arg)
  697. {
  698. if(!arg.IsList())
  699. ArgumentError("values",arg);
  700. const Data& L=arg;
  701. Data ret;
  702. ret.MakeList(L.Size());
  703. for(size_t i=0; i<L.Size(); i++)
  704. if(!L[i].IsList(2))
  705. throw LangErr("values","argument is not a dictionary");
  706. else
  707. ret[i]=L[i][1];
  708. return ret;
  709. }
  710. /// split(s_1,s_2,d) - If $d$ is not givent Split the string $s_1$
  711. /// to pieces separated by the string $s_2$ and return pieces as a
  712. /// list of strings. If $s_2$ is empty string, split the string to
  713. /// single characters. If $d=1$ is given, add delimiters too in the
  714. /// resulting list.
  715. Data split(const Data& arg)
  716. {
  717. if(!(arg.IsList(2) || arg.IsList(3)) || !arg[0].IsString() || !arg[1].IsString())
  718. ArgumentError("split",arg);
  719. bool add_delim=false;
  720. if(arg.IsList(3))
  721. {
  722. if(!arg[2].IsInteger())
  723. ArgumentError("split",arg);
  724. else
  725. add_delim=(arg[2].Integer() == 1);
  726. }
  727. string s1=arg[0].String();
  728. const string& s2=arg[1].String();
  729. Data ret;
  730. if(s2=="")
  731. {
  732. char e[2];
  733. e[1]=0;
  734. ret.MakeList(s1.length());
  735. for(size_t i=0; i<s1.length(); i++)
  736. {
  737. e[0]=s1[i];
  738. ret[i]=e;
  739. }
  740. return ret;
  741. }
  742. size_t n=0,f;
  743. ret.MakeList();
  744. while(1)
  745. {
  746. f=s1.find(s2,n);
  747. if(f > s1.length())
  748. {
  749. if(n < s1.length())
  750. ret.AddList(s1.substr(n,s1.length()));
  751. break;
  752. }
  753. if(f != n)
  754. ret.AddList(s1.substr(n,f-n));
  755. n=f+s2.length();
  756. if(add_delim)
  757. ret.AddList(s2);
  758. }
  759. return ret;
  760. }
  761. /// join(e,s) - If $e$ is a list of strings and $s$ is not given,
  762. /// concatenate the strings together and return the resulting
  763. /// string. With $s$, add a string
  764. /// $s$ between list members.
  765. Data join(const Data& arg)
  766. {
  767. if(!arg.IsList())
  768. ArgumentError("join",arg);
  769. const Data* L;
  770. string j;
  771. if(arg.IsList(2) && arg[0].IsList() && arg[1].IsString())
  772. {
  773. j=arg[1].String();
  774. L=&arg[0];
  775. }
  776. else
  777. L=&arg;
  778. string s;
  779. for(size_t i=0; i<L->Size(); i++)
  780. {
  781. if(i)
  782. s+=j;
  783. if((*L)[i].IsString())
  784. s+=(*L)[i].String();
  785. else
  786. ArgumentError("join",arg);
  787. }
  788. return s;
  789. }
  790. /// toint(e) - If $e$ is an integer return it unchanged. If $e$ is
  791. /// a string, convert value to integer. If $e$ is a real, round to
  792. /// nearest integer and return it. Otherwise, return 0.
  793. Data toint(const Data& arg)
  794. {
  795. if(arg.IsInteger())
  796. return arg;
  797. else if(arg.IsString())
  798. return atoi(arg.String().c_str());
  799. else if(arg.IsReal())
  800. return int(arg.Real()+0.5);
  801. return 0;
  802. }
  803. /// toreal(e) - If $e$ is an integer or a real return it as a
  804. /// real. If $e$ is a string, convert value to real. Otherwise,
  805. /// return 0.0.
  806. Data toreal(const Data& arg)
  807. {
  808. if(arg.IsInteger())
  809. return double(arg.Integer());
  810. else if(arg.IsString())
  811. return atof(arg.String().c_str());
  812. else if(arg.IsReal())
  813. return arg;
  814. return 0.0;
  815. }
  816. /// format(f,e) - Return C-printf formatted string of a real
  817. /// number $f$.
  818. Data format(const Data& arg)
  819. {
  820. if(!arg.IsList(2) || !arg[0].IsString() || (!arg[1].IsReal() && !arg[1].IsInteger()))
  821. ArgumentError("format",arg);
  822. string format=arg[0].String();
  823. const Data& d=arg[1];
  824. double num;
  825. if(d.IsReal())
  826. num=d.Real();
  827. else
  828. num=double(d.Integer());
  829. static char parser_buffer[128];
  830. #ifdef WIN32
  831. sprintf(parser_buffer,format.c_str(),num);
  832. #else
  833. snprintf(parser_buffer,127,format.c_str(),num);
  834. #endif
  835. return Data(parser_buffer);
  836. }
  837. /// lc(s) - Convert string $s$ to lower case.
  838. Data lc(const Data& args)
  839. {
  840. VECTORIZE(lc);
  841. if(!args.IsString())
  842. ArgumentError("lc",args);
  843. string s=args.String();
  844. bool convert=true;
  845. for(size_t i=0; i<s.length(); i++)
  846. {
  847. if(s[i]=='{')
  848. convert=false;
  849. if(s[i]=='}')
  850. convert=true;
  851. if(convert)
  852. s[i]=tolower(s[i]);
  853. }
  854. return s;
  855. }
  856. /// uc(s) - Convert string $s$ to upper case.
  857. Data uc(const Data& args)
  858. {
  859. VECTORIZE(uc);
  860. if(!args.IsString())
  861. ArgumentError("uc",args);
  862. string s=args.String();
  863. bool convert=true;
  864. for(size_t i=0; i<s.length(); i++)
  865. {
  866. if(s[i]=='{')
  867. convert=false;
  868. if(s[i]=='}')
  869. convert=true;
  870. if(convert)
  871. s[i]=toupper(s[i]);
  872. }
  873. return s;
  874. }
  875. /// ucfirst(s) - Convert the first letter of the string $s$ to
  876. /// upper case.
  877. Data ucfirst(const Data& args)
  878. {
  879. VECTORIZE(ucfirst);
  880. if(!args.IsString())
  881. ArgumentError("ucfirst",args);
  882. string s=args.String();
  883. if(s.length())
  884. s[0]=toupper(s[0]);
  885. return s;
  886. }
  887. /// sleep(t) - Wait for $t$ seconds.
  888. Data sleep(const Data& args)
  889. {
  890. if(!args.IsInteger())
  891. ArgumentError("sleep",args);
  892. #if defined(WIN32) || defined(__WIN32__)
  893. Sleep(args.Integer()*1000);
  894. #else
  895. ::sleep(args.Integer());
  896. #endif
  897. return Null;
  898. }
  899. /// find(e,L) - Return index of the first instance of element $e$
  900. /// in a list $L$ or {\tt NULL} if not found. Alternatively find the
  901. /// starting position of the first instance of substring $e$ in a
  902. /// string $L$.
  903. Data find(const Data& args)
  904. {
  905. if(args.IsList(2) && args[0].IsString() && args[1].IsString())
  906. {
  907. const string& f=args[0].String();
  908. const string& s=args[1].String();
  909. if(f=="")
  910. return 0;
  911. size_t i=s.find(f);
  912. if(i < s.length())
  913. return (int)i;
  914. else
  915. return Null;
  916. }
  917. if(!args.IsList(2) || !args[1].IsList())
  918. ArgumentError("find",args);
  919. const Data& e=args[0];
  920. const Data& L=args[1];
  921. for(size_t i=0; i<L.Size(); i++)
  922. if(L[i]==e)
  923. return int(i);
  924. return Null;
  925. }
  926. /// unique(L) - Return unique elements of sorted list $L$.
  927. Data unique(const Data& args)
  928. {
  929. if(!args.IsList())
  930. ArgumentError("unique",args);
  931. Data ret,last;
  932. ret.MakeList();
  933. for(size_t i=0; i<args.Size(); i++)
  934. {
  935. if(i==0 || args[i]!=last)
  936. ret.AddList(args[i]);
  937. last=args[i];
  938. }
  939. return ret;
  940. }
  941. /// date() - Return current day in {\tt \%d.\%m.\%y} format.
  942. Data date(const Data& args)
  943. {
  944. if(!args.IsNull())
  945. ArgumentError("date",args);
  946. char buf[15];
  947. time_t t=::time(0);
  948. strftime(buf,14,"%d.%m.%Y", localtime(&t));
  949. return string(buf);
  950. }
  951. /// time() - Return current time in 24H clock format {\tt \%h:\%m:\%s}.
  952. Data time(const Data& args)
  953. {
  954. if(!args.IsNull())
  955. ArgumentError("time",args);
  956. char buf[50];
  957. time_t t=::time(0);
  958. strftime(buf,49,"%H:%M:%S", localtime(&t));
  959. return string(buf);
  960. }
  961. /// replace(L,s,d) - Replace object L or members of list L having value s with value d.
  962. Data replace(const Data& args)
  963. {
  964. if(!args.IsList(3))
  965. ArgumentError("replace",args);
  966. if(args[0].IsList())
  967. {
  968. Data ret(args[0]);
  969. for(size_t i=0; i<ret.Size(); i++)
  970. {
  971. if(ret[i]==args[1])
  972. ret[i]=args[2];
  973. }
  974. return ret;
  975. }
  976. else
  977. {
  978. if(args[0]==args[1])
  979. return args[2];
  980. else
  981. return args[0];
  982. }
  983. }
  984. /// joker_match(p,s) - Return 1 if string s matches to joker
  985. /// pattern p. If a list of strings is given instead of a single
  986. /// string, then each maching string is returned.
  987. Data joker_match(const Data& args)
  988. {
  989. if(!args.IsList(2) || !args[0].IsString())
  990. ArgumentError("joker_match",args);
  991. if(args[1].IsList())
  992. {
  993. Data ret;
  994. ret.MakeList();
  995. for(size_t i=0; i<args[1].Size(); i++)
  996. if(joker_match(Data(args[0],args[1][i])).Integer())
  997. ret.AddList(args[1][i]);
  998. return ret;
  999. }
  1000. if(!args[1].IsString())
  1001. ArgumentError("joker_match",args);
  1002. return (int)JokerMatch(args[0].String(),args[1].String());
  1003. }
  1004. /// fuzzy(s) - Remove all accents from letters and drop spaces and special characters.
  1005. Data fuzzy(const Data& args)
  1006. {
  1007. VECTORIZE(fuzzy);
  1008. if(!args.IsString())
  1009. ArgumentError("fuzzy",args);
  1010. return Fuzzify(args.String());
  1011. }
  1012. /// trim(s) - Remove spaces from the beginning and from the end string s.
  1013. Data trim(const Data& args)
  1014. {
  1015. VECTORIZE(trim);
  1016. if(!args.IsString())
  1017. ArgumentError("trim",args);
  1018. return Trim(args.String());
  1019. }
  1020. /// read_file(f) - Read a text file f and return list of strings
  1021. /// representing lines of the text file. Return NULL if reading fails.
  1022. Data read_file(const Data& args)
  1023. {
  1024. VECTORIZE(read_file);
  1025. if(!args.IsString())
  1026. ArgumentError("read_file",args);
  1027. string file=args.String();
  1028. security.ReadFile(file);
  1029. ifstream f(file.c_str());
  1030. if(!f)
  1031. return Null;
  1032. string s;
  1033. Data ret;
  1034. ret.MakeList();
  1035. while(f)
  1036. {
  1037. s=readline(f);
  1038. if(!f)
  1039. {
  1040. if(s!="")
  1041. ret.AddList(s);
  1042. break;
  1043. }
  1044. ret.AddList(s);
  1045. }
  1046. return ret;
  1047. }
  1048. /// read_file_raw(f) - Read a text file f and return content as a string.
  1049. /// Return NULL if reading fails.
  1050. Data read_file_raw(const Data& args)
  1051. {
  1052. VECTORIZE(read_file_raw);
  1053. if(!args.IsString())
  1054. ArgumentError("read_file_raw",args);
  1055. string file=args.String();
  1056. security.ReadFile(file);
  1057. ifstream f(file.c_str(), ios_base::binary);
  1058. if(!f)
  1059. return Null;
  1060. string s;
  1061. string ret;
  1062. char chr;
  1063. while(!f.eof())
  1064. {
  1065. f.get(chr);
  1066. if(f.eof())
  1067. break;
  1068. ret.push_back(chr);
  1069. }
  1070. return Data(ret);
  1071. }
  1072. /// write_file(file,lines) - Write text lines to the file.
  1073. /// Return 1 if successful and NULL if fails.
  1074. Data write_file(const Data& args)
  1075. {
  1076. if(!args.IsList(2) || !args[0].IsString() || !args[1].IsList())
  1077. ArgumentError("write_file",args);
  1078. string file=args[0].String();
  1079. security.WriteFile(file);
  1080. for(size_t i=0; i<args[1].Size(); i++)
  1081. if(!args[1][i].IsString())
  1082. throw LangErr("write_file","invalid text line "+tostr(args[1][i]).String());
  1083. ofstream f(file.c_str());
  1084. if(!f)
  1085. return Null;
  1086. for(size_t i=0; i<args[1].Size(); i++)
  1087. f << args[1][i].String() << endl;
  1088. f.close();
  1089. return 1;
  1090. }
  1091. /// write_file_raw(file,data) - Write raw data to the file.
  1092. /// Return 1 if successful and NULL if fails.
  1093. Data write_file_raw(const Data& args)
  1094. {
  1095. if(!args.IsList(2) || !args[0].IsString() || !args[1].IsString())
  1096. ArgumentError("write_file_raw",args);
  1097. string file=args[0].String();
  1098. security.WriteFile(file);
  1099. ofstream f(file.c_str(), ios_base::binary);
  1100. if(!f)
  1101. return Null;
  1102. f << args[1].String();
  1103. f.close();
  1104. return 1;
  1105. }
  1106. /// current_time() - Return the time in seconds since the Epoch as real number.
  1107. Data current_time(const Data& args)
  1108. {
  1109. if(!args.IsNull())
  1110. ArgumentError("current_time",args);
  1111. return (double)::time(0);
  1112. }
  1113. /// diff_time(t1,t2) - Return the time difference from the moment
  1114. /// $t2$ to the moment $t1$ given as seconds (since the Epoch).
  1115. /// The return value is a quadruple ($d$,$h$,$m$,$s$), where $d$ is the
  1116. /// number of days, $h$ is the number of hours, $m$ is the number of
  1117. /// minutes and $s$ is the number of seconds. All return values are
  1118. /// negative if the moment $t2$ is after the moment $t1$.
  1119. Data diff_time(const Data& args)
  1120. {
  1121. if(!args.IsList(2) || (!args[0].IsReal() && !args[0].IsInteger()) || (!args[1].IsReal() && !args[0].IsInteger()))
  1122. ArgumentError("diff_time",args);
  1123. bool neg=false;
  1124. long t1,t2;
  1125. if(args[0].IsReal())
  1126. t1=(long)args[0].Real();
  1127. else
  1128. t1=(long)args[0].Integer();
  1129. if(args[1].IsReal())
  1130. t2=(long)args[1].Real();
  1131. else
  1132. t2=(long)args[1].Integer();
  1133. long t=t1-t2;
  1134. if(t < 0)
  1135. {
  1136. neg=true;
  1137. t=-t;
  1138. }
  1139. int s,m,h,d;
  1140. d=(int)t/(60*60*24);
  1141. t=t-d*(60*60*24);
  1142. h=(int)t/(60*60);
  1143. t=t-h*(60*60);
  1144. m=(int)t/60;
  1145. t=t-m*60;
  1146. s=(int)t;
  1147. Data ret;
  1148. ret.MakeList(4);
  1149. ret[0]=s;
  1150. ret[1]=m;
  1151. ret[2]=h;
  1152. ret[3]=d;
  1153. if(neg)
  1154. {
  1155. ret[0]=-ret[0];
  1156. ret[1]=-ret[1];
  1157. ret[2]=-ret[2];
  1158. ret[3]=-ret[3];
  1159. }
  1160. return ret;
  1161. }
  1162. /// languages(code) - Return a dictionary mapping ISO639 language
  1163. /// codes to language names.
  1164. Data languages(const Data& args)
  1165. {
  1166. map<string,string> codes=Localization::Languages();
  1167. Data ret;
  1168. ret.MakeList(codes.size());
  1169. map<string,string>::const_iterator i;
  1170. size_t j=0;
  1171. for(i=codes.begin(); i!=codes.end(); i++)
  1172. {
  1173. ret[j].MakeList(2);
  1174. ret[j][0]=(*i).first;
  1175. ret[j][1]=(*i).second;
  1176. j++;
  1177. }
  1178. return ret;
  1179. }
  1180. /// get_lang() - Return current localization language.
  1181. Data get_lang(const Data& args)
  1182. {
  1183. if(!args.IsNull())
  1184. ArgumentError("get_lang",args);
  1185. return Localization::GetLanguage();
  1186. }
  1187. /// set_lang(code) - Select current language for localization.
  1188. Data set_lang(const Data& args)
  1189. {
  1190. if(!args.IsString())
  1191. ArgumentError("set_lang",args);
  1192. string old=Localization::GetLanguage();
  1193. string code=args.String();
  1194. if(!Localization::IsLanguage(code))
  1195. throw LangErr("set_lang()","invalid language code "+code);
  1196. Localization::SetLanguage(code);
  1197. return old;
  1198. }
  1199. /// L(msg,[arg1],[arg2]) - Localize a message.
  1200. Data L(const Data& args)
  1201. {
  1202. if(args.IsString())
  1203. return Localization::Message(args.String());
  1204. if(args.IsList(2) && args[0].IsString() && args[1].IsString())
  1205. return Localization::Message(args[0].String(),args[1].String());
  1206. if(args.IsList(3) && args[0].IsString() && args[1].IsString() && args[2].IsString())
  1207. return Localization::Message(args[0].String(),args[1].String(),args[2].String());
  1208. ArgumentError("L",args);
  1209. return Null;
  1210. }
  1211. /// isdict(L) - Return 1 if L is a dictionary.
  1212. Data isdict(const Data& args)
  1213. {
  1214. if(!args.IsList())
  1215. return 0;
  1216. for(size_t i=0; i<args.Size(); i++)
  1217. {
  1218. if(!args[i].IsList(2))
  1219. return 0;
  1220. if(i)
  1221. if(args[i]<args[i-1] || args[i]==args[i-1])
  1222. return 0;
  1223. }
  1224. return 1;
  1225. }
  1226. /// tr(s,a,b) - Replace every character in string a found from string s with b.
  1227. Data tr(const Data& args)
  1228. {
  1229. if(!args.IsList(3) || !args[0].IsString()
  1230. || !args[1].IsString() || !args[2].IsString())
  1231. ArgumentError("tr",args);
  1232. const string& s=args[0].String();
  1233. const string& a=args[1].String();
  1234. const string& b=args[2].String();
  1235. string ret;
  1236. for(size_t i=0; i<s.length(); i++)
  1237. if(a.find(s[i])!=string::npos)
  1238. ret=ret+b;
  1239. else
  1240. ret=ret+s[i];
  1241. return ret;
  1242. }
  1243. /// strreplace(s,a,b) - Replace every instance of string a
  1244. /// found from string s with b. Return NULL on if infinite recursive replacement.
  1245. Data strreplace(const Data& args)
  1246. {
  1247. if(!args.IsList(3) || !args[0].IsString()
  1248. || !args[1].IsString() || !args[2].IsString())
  1249. ArgumentError("tr",args);
  1250. const string& a=args[1].String();
  1251. const string& b=args[2].String();
  1252. string ret=args[0].String();
  1253. if(a=="" || ret=="")
  1254. return ret;
  1255. if(b.find(a)!=string::npos)
  1256. return Null;
  1257. size_t i;
  1258. while((i=ret.find(a))!=string::npos)
  1259. ret.replace(i,a.length(),b);
  1260. return ret;
  1261. }
  1262. /// hexencode(s) - Encode non-ascii characters.
  1263. Data hexencode(const Data& args)
  1264. {
  1265. VECTORIZE(hexencode);
  1266. if(!args.IsString())
  1267. ArgumentError("hexencode",args);
  1268. string s=args.String();
  1269. string ret;
  1270. for(size_t i=0; i<s.length(); i++)
  1271. ret+=ToHex(s[i]);
  1272. return Data(ret);
  1273. }
  1274. /// hexdecode(s) - Decode hexencoded() string.
  1275. Data hexdecode(const Data& args)
  1276. {
  1277. VECTORIZE(hexdecode);
  1278. if(!args.IsString())
  1279. ArgumentError("hexdecode",args);
  1280. string s=args.String();
  1281. string ret;
  1282. for(size_t i=0; i<s.length(); i+=2)
  1283. ret.push_back(ToChar(s.substr(i,2)));
  1284. return Data(ret);
  1285. }
  1286. // Initialization code
  1287. namespace Lib
  1288. {
  1289. class LibraryInitializer
  1290. {
  1291. public:
  1292. LibraryInitializer()
  1293. {
  1294. external_function["L"]=&L;
  1295. external_function["array"]=&array;
  1296. external_function["copy"]=&copy;
  1297. external_function["count"]=&count;
  1298. external_function["current_time"]=&current_time;
  1299. external_function["date"]=&date;
  1300. external_function["diff_time"]=&diff_time;
  1301. external_function["find"]=&find;
  1302. external_function["first"]=&first;
  1303. external_function["flatten"]=&flatten;
  1304. external_function["format"]=&format;
  1305. external_function["fuzzy"]=&fuzzy;
  1306. external_function["get_lang"]=&get_lang;
  1307. external_function["has_entry"]=&has_entry;
  1308. external_function["head"]=&head;
  1309. external_function["hexdecode"]=&hexdecode;
  1310. external_function["hexencode"]=&hexencode;
  1311. external_function["index"]=&index;
  1312. external_function["isdict"]=&isdict;
  1313. external_function["join"]=&join;
  1314. external_function["joker_match"]=&joker_match;
  1315. external_function["languages"]=&languages;
  1316. external_function["last"]=&last;
  1317. external_function["lc"]=&lc;
  1318. external_function["left"]=&left;
  1319. external_function["length"]=&length;
  1320. external_function["max"]=&max;
  1321. external_function["min"]=&min;
  1322. external_function["print"]=&print;
  1323. external_function["println"]=&println;
  1324. external_function["quit"]=&quit;
  1325. external_function["random"]=&random;
  1326. external_function["randomize"]=&randomize;
  1327. external_function["read_file"]=&read_file;
  1328. external_function["read_file_raw"]=&read_file_raw;
  1329. external_function["replace"]=&replace;
  1330. external_function["reverse"]=&reverse;
  1331. external_function["right"]=&right;
  1332. external_function["seq"]=&seq;
  1333. external_function["set_lang"]=&set_lang;
  1334. external_function["shuffle"]=&shuffle;
  1335. external_function["sleep"]=&Evaluator::sleep;
  1336. external_function["sort"]=&sort;
  1337. external_function["split"]=&split;
  1338. external_function["strreplace"]=&strreplace;
  1339. external_function["substr"]=&substr;
  1340. external_function["tail"]=&tail;
  1341. external_function["time"]=&time;
  1342. external_function["toint"]=&toint;
  1343. external_function["toreal"]=&toreal;
  1344. external_function["tostr"]=&tostr;
  1345. external_function["toval"]=&toval;
  1346. external_function["tr"]=&tr;
  1347. external_function["trim"]=&trim;
  1348. external_function["typeof"]=&type_of;
  1349. external_function["uc"]=&uc;
  1350. external_function["ucfirst"]=&ucfirst;
  1351. external_function["unique"]=&unique;
  1352. external_function["values"]=&values;
  1353. external_function["write_file"]=&write_file;
  1354. external_function["write_file_raw"]=&write_file_raw;
  1355. }
  1356. };
  1357. static LibraryInitializer initializer;
  1358. }
  1359. }