libc.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /*
  2. * Copyright t lefering, David Given
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * These are the four essential freedoms with GNU GPL software:
  18. * 1: freedom to run the program, for any purpose
  19. * 2: freedom to study how the program works, and change it to make it do what you wish
  20. * 3: freedom to redistribute copies to help your Free Software friends
  21. * 4: freedom to distribute copies of your modified versions to your Free Software friends
  22. * , ,
  23. * / \
  24. * ((__-^^-,-^^-__))
  25. * `-_---' `---_-'
  26. * `--|o` 'o|--'
  27. * \ ` /
  28. * ): :(
  29. * :o_o:
  30. * "-"
  31. */
  32. /****************************************************************************
  33. * PRINTF *
  34. ****************************************************************************/
  35. /* This is a copy of Ash Searle's public domain sprintf function. See:
  36. * http://hexmen.com/blog/2007/03/printf-sprintf/
  37. * ...for more info.
  38. */
  39. /**
  40. * JavaScript printf/sprintf functions.
  41. *
  42. * This code is unrestricted: you are free to use it however you like.
  43. *
  44. * The functions should work as expected, performing left or right alignment,
  45. * truncating strings, outputting numbers with a required precision etc.
  46. *
  47. * For complex cases, these functions follow the Perl implementations of
  48. * (s)printf, allowing arguments to be passed out-of-order, and to set the
  49. * precision or length of the output based on arguments instead of fixed
  50. * numbers.
  51. *
  52. * See http://perldoc.perl.org/functions/sprintf.html for more information.
  53. *
  54. * Implemented:
  55. * - zero and space-padding
  56. * - right and left-alignment,
  57. * - base X prefix (binary, octal and hex)
  58. * - positive number prefix
  59. * - (minimum) width
  60. * - precision / truncation / maximum width
  61. * - out of order arguments
  62. *
  63. * Not implemented (yet):
  64. * - vector flag
  65. * - size (bytes, words, long-words etc.)
  66. *
  67. * Will not implement:
  68. * - %n or %p (no pass-by-reference in JavaScript)
  69. *
  70. * @version 2007.04.27
  71. * @author Ash Searle
  72. */
  73. function sprintf()
  74. {
  75. function pad(str, len, chr, leftJustify)
  76. {
  77. var padding = (str.length >= len) ? '' : Array(
  78. 1 + len - str.length >>> 0).join(chr);
  79. return leftJustify ? str + padding : padding + str;
  80. }
  81. function justify(value, prefix, leftJustify, minWidth, zeroPad)
  82. {
  83. var diff = minWidth - value.length;
  84. if (diff > 0)
  85. {
  86. if (leftJustify || !zeroPad)
  87. {
  88. value = pad(value, minWidth, ' ', leftJustify);
  89. }
  90. else
  91. {
  92. value = value.slice(0, prefix.length)
  93. + pad('', diff, '0', true) + value.slice(prefix.length);
  94. }
  95. }
  96. return value;
  97. }
  98. function formatBaseX(value, base, prefix, leftJustify, minWidth, precision,
  99. zeroPad)
  100. {
  101. // Note: casts negative numbers to positive ones
  102. var number = value >>> 0;
  103. prefix = prefix && number &&
  104. {
  105. '2' :'0b',
  106. '8' :'0',
  107. '16' :'0x'
  108. }[base] || '';
  109. value = prefix + pad(number.toString(base), precision || 0, '0', false);
  110. return justify(value, prefix, leftJustify, minWidth, zeroPad);
  111. }
  112. function formatString(value, leftJustify, minWidth, precision, zeroPad)
  113. {
  114. if (precision != null)
  115. {
  116. value = value.slice(0, precision);
  117. }
  118. return justify(value, '', leftJustify, minWidth, zeroPad);
  119. }
  120. var a = arguments, i = 0, format = a[i++];
  121. /* Foul hack to remove simple uses of %l, which aren't supported. */
  122. format.replace("[^%]%l", "%");
  123. format.replace("^%l", "%");
  124. return format
  125. .replace(
  126. sprintf.regex,
  127. function(substring, valueIndex, flags, minWidth, _,
  128. precision, type)
  129. {
  130. if (substring == '%%')
  131. return '%';
  132. // parse flags
  133. var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false;
  134. for ( var j = 0; flags && j < flags.length; j++)
  135. switch (flags.charAt(j))
  136. {
  137. case ' ':
  138. positivePrefix = ' ';
  139. break;
  140. case '+':
  141. positivePrefix = '+';
  142. break;
  143. case '-':
  144. leftJustify = true;
  145. break;
  146. case '0':
  147. zeroPad = true;
  148. break;
  149. case '#':
  150. prefixBaseX = true;
  151. break;
  152. }
  153. // parameters may be null, undefined, empty-string or
  154. // real valued
  155. // we want to ignore null, undefined and empty-string
  156. // values
  157. if (!minWidth)
  158. {
  159. minWidth = 0;
  160. }
  161. else if (minWidth == '*')
  162. {
  163. minWidth = +a[i++];
  164. }
  165. else if (minWidth.charAt(0) == '*')
  166. {
  167. minWidth = +a[minWidth.slice(1, -1)];
  168. }
  169. else
  170. {
  171. minWidth = +minWidth;
  172. }
  173. // Note: undocumented perl feature:
  174. if (minWidth < 0)
  175. {
  176. minWidth = -minWidth;
  177. leftJustify = true;
  178. }
  179. if (!isFinite(minWidth))
  180. {
  181. throw new Error(
  182. 'sprintf: (minimum-)width must be finite');
  183. }
  184. if (!precision)
  185. {
  186. precision = 'fFeE'.indexOf(type) > -1 ? 6
  187. : (type == 'd') ? 0 : void (0);
  188. }
  189. else if (precision == '*')
  190. {
  191. precision = +a[i++];
  192. }
  193. else if (precision.charAt(0) == '*')
  194. {
  195. precision = +a[precision.slice(1, -1)];
  196. }
  197. else
  198. {
  199. precision = +precision;
  200. }
  201. // grab value using valueIndex if required?
  202. var value = valueIndex ? a[valueIndex.slice(0, -1)]
  203. : a[i++];
  204. switch (type)
  205. {
  206. case 's':
  207. return formatString(String(value), leftJustify,
  208. minWidth, precision, zeroPad);
  209. case 'c':
  210. return formatString(
  211. String.fromCharCode(+value),
  212. leftJustify, minWidth, precision,
  213. zeroPad);
  214. case 'b':
  215. return formatBaseX(value, 2, prefixBaseX,
  216. leftJustify, minWidth, precision,
  217. zeroPad);
  218. case 'o':
  219. return formatBaseX(value, 8, prefixBaseX,
  220. leftJustify, minWidth, precision,
  221. zeroPad);
  222. case 'x':
  223. return formatBaseX(value, 16, prefixBaseX,
  224. leftJustify, minWidth, precision,
  225. zeroPad);
  226. case 'X':
  227. return formatBaseX(value, 16, prefixBaseX,
  228. leftJustify, minWidth, precision,
  229. zeroPad).toUpperCase();
  230. case 'u':
  231. return formatBaseX(value, 10, prefixBaseX,
  232. leftJustify, minWidth, precision,
  233. zeroPad);
  234. case 'i':
  235. case 'd':
  236. {
  237. var number = parseInt(+value);
  238. var prefix = number < 0 ? '-' : positivePrefix;
  239. value = prefix
  240. + pad(String(Math.abs(number)),
  241. precision, '0', false);
  242. return justify(value, prefix, leftJustify,
  243. minWidth, zeroPad);
  244. }
  245. case 'e':
  246. case 'E':
  247. case 'f':
  248. case 'F':
  249. case 'g':
  250. case 'G':
  251. {
  252. var number = +value;
  253. var prefix = number < 0 ? '-' : positivePrefix;
  254. var method =
  255. [
  256. 'toExponential', 'toFixed',
  257. 'toPrecision'
  258. ]['efg'.indexOf(type.toLowerCase())];
  259. var textTransform =
  260. [
  261. 'toString', 'toUpperCase'
  262. ]['eEfFgG'.indexOf(type) % 2];
  263. value = prefix
  264. + Math.abs(number)[method](precision);
  265. return justify(value, prefix, leftJustify,
  266. minWidth, zeroPad)[textTransform]();
  267. }
  268. default:
  269. return substring;
  270. }
  271. });
  272. }
  273. sprintf.regex = /%%|%(\d+\$)?([-+#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
  274. /****************************************************************************
  275. * STDIO *
  276. ****************************************************************************/
  277. var clue_output_buffer = "";
  278. var __stdout = 0;
  279. function clue_add_to_output_buffer(s)
  280. {
  281. clue_output_buffer += s;
  282. }
  283. function clue_flush_output_buffer()
  284. {
  285. var strings = clue_output_buffer.split("\n")
  286. for (var i = 0; i < (strings.length - 1); i++)
  287. print(strings[i]);
  288. clue_output_buffer = strings[strings.length - 1];
  289. }
  290. function _printf(stackpo, stackpd, formatpo, formatpd)
  291. {
  292. var format = clue_ptrtostring(formatpo, formatpd);
  293. var outargs = [format];
  294. var numargs = arguments.length;
  295. var i = 4;
  296. while (i < numargs)
  297. {
  298. var thisarg = arguments[i];
  299. i++;
  300. if (i < (numargs-1))
  301. {
  302. var nextarg = arguments[i];
  303. if (!nextarg || (typeof(nextarg) == "object"))
  304. {
  305. // If the next argument is nil or a table, then we must
  306. // be looking at a register pair representing a pointer.
  307. thisarg = clue_ptrtostring(thisarg, nextarg);
  308. i++;
  309. }
  310. }
  311. outargs.push(thisarg);
  312. }
  313. clue_add_to_output_buffer(sprintf.apply(null, outargs));
  314. clue_flush_output_buffer();
  315. return 1
  316. }
  317. function _putc(sp, stack, c, fppo, fppd)
  318. {
  319. clue_add_to_output_buffer(String.fromCharCode(c));
  320. if (c == '\n')
  321. clue_flush_output_buffer();
  322. }
  323. function _atoi(sp, stack, po, pd)
  324. {
  325. var s = clue_ptrtostring(po, pd);
  326. return s|0;
  327. }
  328. var _atol = _atoi;
  329. /****************************************************************************
  330. * STRINGS *
  331. ****************************************************************************/
  332. function _strcpy(sp, stack, destpo, destpd, srcpo, srcpd)
  333. {
  334. var origdestpo = destpo;
  335. for (;;)
  336. {
  337. var c = srcpd[srcpo];
  338. destpd[destpo] = c;
  339. srcpo++;
  340. destpo++;
  341. if (!c)
  342. break;
  343. }
  344. return [origdestpo, destpd];
  345. }
  346. function _memset(sp, stack, destpo, destpd, c, n)
  347. {
  348. for (var offset = 0; offset < (n-1); offset++)
  349. destpd[destpo + offset] = c;
  350. return [destpo, destpd];
  351. }
  352. /****************************************************************************
  353. * TIME *
  354. ****************************************************************************/
  355. function _gettimeofday(sp, stack, tvpo, tvpd, tzpo, tzpd)
  356. {
  357. var t = new Date().getTime();
  358. var secs = (t / 1000) | 0;
  359. var usecs = (t % 1000) * 1000;
  360. tvpd[tvpo+0] = secs;
  361. tvpd[tvpo+1] = usecs;
  362. return 0;
  363. }
  364. /****************************************************************************
  365. * MATHS *
  366. ****************************************************************************/
  367. function _sin(sp, stack, n) { return Math.sin(n); }
  368. function _cos(sp, stack, n) { return Math.cos(n); }
  369. function _atan(sp, stack, n) { return Math.atan(n); }
  370. function _pow(sp, stack, x, y) { return Math.pow(x, y); }
  371. function _log(sp, stack, n) { return Math.log(n); }
  372. function _exp(sp, stack, n) { return Math.exp(n); }
  373. function _sqrt(sp, stack, n) { return Math.sqrt(n); }
  374. /****************************************************************************
  375. * MEMORY *
  376. ****************************************************************************/
  377. function _malloc(sp, stack, size)
  378. {
  379. return [0, []];
  380. }
  381. function _calloc(sp, stack, size1, size2)
  382. {
  383. var d = [];
  384. for (var i = 0; i < (size1*size2); i++)
  385. d[i] = 0;
  386. return [0, d];
  387. }
  388. function _free(sp, stack, po, pd)
  389. {
  390. }
  391. function _realloc(sp, stack, po, pd, size)
  392. {
  393. return [po, pd];
  394. }