/src/library.js

http://github.com/kripken/emscripten · JavaScript · 5230 lines · 4193 code · 440 blank · 597 comment · 606 complexity · 028ee4a72ec90bfc4e88dbdf0ec6f56c MD5 · raw file

  1. /**
  2. * @license
  3. * Copyright 2010 The Emscripten Authors
  4. * SPDX-License-Identifier: MIT
  5. */
  6. //"use strict";
  7. // An implementation of basic necessary libraries for the web. This integrates
  8. // with a compiled libc and with the rest of the JS runtime.
  9. //
  10. // We search the Library object when there is an external function. If the
  11. // entry in the Library is a function, we insert it. If it is a string, we
  12. // do another lookup in the library (a simple way to write a function once,
  13. // if it can be called by different names). We also allow dependencies,
  14. // using __deps. Initialization code to be run after allocating all
  15. // global constants can be defined by __postset.
  16. //
  17. // Note that the full function name will be '_' + the name in the Library
  18. // object. For convenience, the short name appears here. Note that if you add a
  19. // new function with an '_', it will not be found.
  20. // Memory allocated during startup, in postsets, should only be static
  21. // (using makeStaticAlloc)
  22. LibraryManager.library = {
  23. #if !WASM_BACKEND
  24. __dso_handle: '{{{ makeStaticAlloc(1) }}}',
  25. #endif
  26. // ==========================================================================
  27. // getTempRet0/setTempRet0: scratch space handling i64 return
  28. // ==========================================================================
  29. getTempRet0__sig: 'i',
  30. getTempRet0: function() {
  31. return {{{ makeGetTempRet0() }}};
  32. },
  33. setTempRet0__sig: 'vi',
  34. setTempRet0: function($i) {
  35. {{{ makeSetTempRet0('$i') }}};
  36. },
  37. // ==========================================================================
  38. // JavaScript <-> C string interop
  39. // ==========================================================================
  40. $stringToNewUTF8: function(jsString) {
  41. var length = lengthBytesUTF8(jsString)+1;
  42. var cString = _malloc(length);
  43. stringToUTF8(jsString, cString, length);
  44. return cString;
  45. },
  46. // ==========================================================================
  47. // utime.h
  48. // ==========================================================================
  49. utime__deps: ['$FS', '$setErrNo'],
  50. utime__proxy: 'sync',
  51. utime__sig: 'iii',
  52. utime: function(path, times) {
  53. // int utime(const char *path, const struct utimbuf *times);
  54. // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/utime.h.html
  55. var time;
  56. if (times) {
  57. // NOTE: We don't keep track of access timestamps.
  58. var offset = {{{ C_STRUCTS.utimbuf.modtime }}};
  59. time = {{{ makeGetValue('times', 'offset', 'i32') }}};
  60. time *= 1000;
  61. } else {
  62. time = Date.now();
  63. }
  64. path = UTF8ToString(path);
  65. try {
  66. FS.utime(path, time, time);
  67. return 0;
  68. } catch (e) {
  69. FS.handleFSError(e);
  70. return -1;
  71. }
  72. },
  73. utimes__deps: ['$FS', '$setErrNo'],
  74. utimes__proxy: 'sync',
  75. utimes__sig: 'iii',
  76. utimes: function(path, times) {
  77. var time;
  78. if (times) {
  79. var offset = {{{ C_STRUCTS.timeval.__size__ }}} + {{{ C_STRUCTS.timeval.tv_sec }}};
  80. time = {{{ makeGetValue('times', 'offset', 'i32') }}} * 1000;
  81. offset = {{{ C_STRUCTS.timeval.__size__ }}} + {{{ C_STRUCTS.timeval.tv_usec }}};
  82. time += {{{ makeGetValue('times', 'offset', 'i32') }}} / 1000;
  83. } else {
  84. time = Date.now();
  85. }
  86. path = UTF8ToString(path);
  87. try {
  88. FS.utime(path, time, time);
  89. return 0;
  90. } catch (e) {
  91. FS.handleFSError(e);
  92. return -1;
  93. }
  94. },
  95. // ==========================================================================
  96. // sys/file.h
  97. // ==========================================================================
  98. flock: function(fd, operation) {
  99. // int flock(int fd, int operation);
  100. // Pretend to succeed
  101. return 0;
  102. },
  103. chroot__deps: ['$setErrNo'],
  104. chroot__proxy: 'sync',
  105. chroot__sig: 'ii',
  106. chroot: function(path) {
  107. // int chroot(const char *path);
  108. // http://pubs.opengroup.org/onlinepubs/7908799/xsh/chroot.html
  109. setErrNo({{{ cDefine('EACCES') }}});
  110. return -1;
  111. },
  112. fpathconf__deps: ['$setErrNo'],
  113. fpathconf__proxy: 'sync',
  114. fpathconf__sig: 'iii',
  115. fpathconf: function(fildes, name) {
  116. // long fpathconf(int fildes, int name);
  117. // http://pubs.opengroup.org/onlinepubs/000095399/functions/encrypt.html
  118. // NOTE: The first parameter is ignored, so pathconf == fpathconf.
  119. // The constants here aren't real values. Just mimicking glibc.
  120. switch (name) {
  121. case {{{ cDefine('_PC_LINK_MAX') }}}:
  122. return 32000;
  123. case {{{ cDefine('_PC_MAX_CANON') }}}:
  124. case {{{ cDefine('_PC_MAX_INPUT') }}}:
  125. case {{{ cDefine('_PC_NAME_MAX') }}}:
  126. return 255;
  127. case {{{ cDefine('_PC_PATH_MAX') }}}:
  128. case {{{ cDefine('_PC_PIPE_BUF') }}}:
  129. case {{{ cDefine('_PC_REC_MIN_XFER_SIZE') }}}:
  130. case {{{ cDefine('_PC_REC_XFER_ALIGN') }}}:
  131. case {{{ cDefine('_PC_ALLOC_SIZE_MIN') }}}:
  132. return 4096;
  133. case {{{ cDefine('_PC_CHOWN_RESTRICTED') }}}:
  134. case {{{ cDefine('_PC_NO_TRUNC') }}}:
  135. case {{{ cDefine('_PC_2_SYMLINKS') }}}:
  136. return 1;
  137. case {{{ cDefine('_PC_VDISABLE') }}}:
  138. return 0;
  139. case {{{ cDefine('_PC_SYNC_IO') }}}:
  140. case {{{ cDefine('_PC_ASYNC_IO') }}}:
  141. case {{{ cDefine('_PC_PRIO_IO') }}}:
  142. case {{{ cDefine('_PC_SOCK_MAXBUF') }}}:
  143. case {{{ cDefine('_PC_REC_INCR_XFER_SIZE') }}}:
  144. case {{{ cDefine('_PC_REC_MAX_XFER_SIZE') }}}:
  145. case {{{ cDefine('_PC_SYMLINK_MAX') }}}:
  146. return -1;
  147. case {{{ cDefine('_PC_FILESIZEBITS') }}}:
  148. return 64;
  149. }
  150. setErrNo({{{ cDefine('EINVAL') }}});
  151. return -1;
  152. },
  153. pathconf: 'fpathconf',
  154. confstr__deps: ['$setErrNo', '$ENV'],
  155. confstr__proxy: 'sync',
  156. confstr__sig: 'iiii',
  157. confstr: function(name, buf, len) {
  158. // size_t confstr(int name, char *buf, size_t len);
  159. // http://pubs.opengroup.org/onlinepubs/000095399/functions/confstr.html
  160. var value;
  161. switch (name) {
  162. case {{{ cDefine('_CS_PATH') }}}:
  163. value = ENV['PATH'] || '/';
  164. break;
  165. case {{{ cDefine('_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS') }}}:
  166. // Mimicking glibc.
  167. value = 'POSIX_V6_ILP32_OFF32\nPOSIX_V6_ILP32_OFFBIG';
  168. break;
  169. case {{{ cDefine('_CS_GNU_LIBC_VERSION') }}}:
  170. // This JS implementation was tested against this glibc version.
  171. value = 'glibc 2.14';
  172. break;
  173. case {{{ cDefine('_CS_GNU_LIBPTHREAD_VERSION') }}}:
  174. // We don't support pthreads.
  175. value = '';
  176. break;
  177. case {{{ cDefine('_CS_POSIX_V6_ILP32_OFF32_LIBS') }}}:
  178. case {{{ cDefine('_CS_POSIX_V6_ILP32_OFFBIG_LIBS') }}}:
  179. case {{{ cDefine('_CS_POSIX_V6_LP64_OFF64_CFLAGS') }}}:
  180. case {{{ cDefine('_CS_POSIX_V6_LP64_OFF64_LDFLAGS') }}}:
  181. case {{{ cDefine('_CS_POSIX_V6_LP64_OFF64_LIBS') }}}:
  182. case {{{ cDefine('_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS') }}}:
  183. case {{{ cDefine('_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS') }}}:
  184. case {{{ cDefine('_CS_POSIX_V6_LPBIG_OFFBIG_LIBS') }}}:
  185. value = '';
  186. break;
  187. case {{{ cDefine('_CS_POSIX_V6_ILP32_OFF32_CFLAGS') }}}:
  188. case {{{ cDefine('_CS_POSIX_V6_ILP32_OFF32_LDFLAGS') }}}:
  189. case {{{ cDefine('_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS') }}}:
  190. value = '-m32';
  191. break;
  192. case {{{ cDefine('_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS') }}}:
  193. value = '-m32 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64';
  194. break;
  195. default:
  196. setErrNo({{{ cDefine('EINVAL') }}});
  197. return 0;
  198. }
  199. if (len == 0 || buf == 0) {
  200. return value.length + 1;
  201. } else {
  202. var length = Math.min(len, value.length);
  203. for (var i = 0; i < length; i++) {
  204. {{{ makeSetValue('buf', 'i', 'value.charCodeAt(i)', 'i8') }}};
  205. }
  206. if (len > length) {{{ makeSetValue('buf', 'i++', '0', 'i8') }}};
  207. return i;
  208. }
  209. },
  210. execl__deps: ['$setErrNo'],
  211. execl__sig: 'iiii',
  212. execl: function(path, arg0, varArgs) {
  213. // int execl(const char *path, const char *arg0, ... /*, (char *)0 */);
  214. // http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html
  215. // We don't support executing external code.
  216. setErrNo({{{ cDefine('ENOEXEC') }}});
  217. return -1;
  218. },
  219. execle: 'execl',
  220. execlp: 'execl',
  221. execv: 'execl',
  222. execve: 'execl',
  223. execvp: 'execl',
  224. __execvpe: 'execl',
  225. fexecve: 'execl',
  226. exit__sig: 'vi',
  227. exit: function(status) {
  228. #if MINIMAL_RUNTIME
  229. throw 'exit(' + status + ')';
  230. #else
  231. // void _exit(int status);
  232. // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html
  233. exit(status);
  234. #endif
  235. },
  236. _exit__sig: 'vi',
  237. _exit: 'exit',
  238. _Exit__sig: 'vi',
  239. _Exit: 'exit',
  240. #if MINIMAL_RUNTIME
  241. $exit: function(status) {
  242. throw 'exit(' + status + ')';
  243. },
  244. #endif
  245. fork__deps: ['$setErrNo'],
  246. fork__sig: 'i',
  247. fork: function() {
  248. // pid_t fork(void);
  249. // http://pubs.opengroup.org/onlinepubs/000095399/functions/fork.html
  250. // We don't support multiple processes.
  251. setErrNo({{{ cDefine('EAGAIN') }}});
  252. return -1;
  253. },
  254. vfork: 'fork',
  255. posix_spawn: 'fork',
  256. posix_spawnp: 'fork',
  257. setgroups__deps: ['$setErrNo', 'sysconf'],
  258. setgroups: function(ngroups, gidset) {
  259. // int setgroups(int ngroups, const gid_t *gidset);
  260. // https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/setgroups.2.html
  261. if (ngroups < 1 || ngroups > _sysconf({{{ cDefine('_SC_NGROUPS_MAX') }}})) {
  262. setErrNo({{{ cDefine('EINVAL') }}});
  263. return -1;
  264. } else {
  265. // We have just one process/user/group, so it makes no sense to set groups.
  266. setErrNo({{{ cDefine('EPERM') }}});
  267. return -1;
  268. }
  269. },
  270. sysconf__deps: ['$setErrNo'],
  271. sysconf__proxy: 'sync',
  272. sysconf__sig: 'ii',
  273. sysconf: function(name) {
  274. // long sysconf(int name);
  275. // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html
  276. switch(name) {
  277. case {{{ cDefine('_SC_PAGE_SIZE') }}}: return {{{ POSIX_PAGE_SIZE }}};
  278. case {{{ cDefine('_SC_PHYS_PAGES') }}}:
  279. #if ALLOW_MEMORY_GROWTH
  280. #if MAXIMUM_MEMORY == -1 // no maximum set, assume the best
  281. var maxHeapSize = 4*1024*1024*1024;
  282. #else
  283. var maxHeapSize = {{{ MAXIMUM_MEMORY }}};
  284. #endif
  285. #else // no growth
  286. var maxHeapSize = HEAPU8.length;
  287. #endif
  288. return maxHeapSize / {{{ POSIX_PAGE_SIZE }}};
  289. case {{{ cDefine('_SC_ADVISORY_INFO') }}}:
  290. case {{{ cDefine('_SC_BARRIERS') }}}:
  291. case {{{ cDefine('_SC_ASYNCHRONOUS_IO') }}}:
  292. case {{{ cDefine('_SC_CLOCK_SELECTION') }}}:
  293. case {{{ cDefine('_SC_CPUTIME') }}}:
  294. case {{{ cDefine('_SC_FSYNC') }}}:
  295. case {{{ cDefine('_SC_IPV6') }}}:
  296. case {{{ cDefine('_SC_MAPPED_FILES') }}}:
  297. case {{{ cDefine('_SC_MEMLOCK') }}}:
  298. case {{{ cDefine('_SC_MEMLOCK_RANGE') }}}:
  299. case {{{ cDefine('_SC_MEMORY_PROTECTION') }}}:
  300. case {{{ cDefine('_SC_MESSAGE_PASSING') }}}:
  301. case {{{ cDefine('_SC_MONOTONIC_CLOCK') }}}:
  302. case {{{ cDefine('_SC_PRIORITIZED_IO') }}}:
  303. case {{{ cDefine('_SC_PRIORITY_SCHEDULING') }}}:
  304. case {{{ cDefine('_SC_RAW_SOCKETS') }}}:
  305. case {{{ cDefine('_SC_READER_WRITER_LOCKS') }}}:
  306. case {{{ cDefine('_SC_REALTIME_SIGNALS') }}}:
  307. case {{{ cDefine('_SC_SEMAPHORES') }}}:
  308. case {{{ cDefine('_SC_SHARED_MEMORY_OBJECTS') }}}:
  309. case {{{ cDefine('_SC_SPAWN') }}}:
  310. case {{{ cDefine('_SC_SPIN_LOCKS') }}}:
  311. case {{{ cDefine('_SC_SYNCHRONIZED_IO') }}}:
  312. case {{{ cDefine('_SC_THREAD_ATTR_STACKADDR') }}}:
  313. case {{{ cDefine('_SC_THREAD_ATTR_STACKSIZE') }}}:
  314. case {{{ cDefine('_SC_THREAD_CPUTIME') }}}:
  315. case {{{ cDefine('_SC_THREAD_PRIO_INHERIT') }}}:
  316. case {{{ cDefine('_SC_THREAD_PRIO_PROTECT') }}}:
  317. case {{{ cDefine('_SC_THREAD_PROCESS_SHARED') }}}:
  318. case {{{ cDefine('_SC_THREAD_SAFE_FUNCTIONS') }}}:
  319. case {{{ cDefine('_SC_THREADS') }}}:
  320. case {{{ cDefine('_SC_TIMEOUTS') }}}:
  321. case {{{ cDefine('_SC_TIMERS') }}}:
  322. case {{{ cDefine('_SC_VERSION') }}}:
  323. case {{{ cDefine('_SC_2_C_BIND') }}}:
  324. case {{{ cDefine('_SC_2_C_DEV') }}}:
  325. case {{{ cDefine('_SC_2_CHAR_TERM') }}}:
  326. case {{{ cDefine('_SC_2_LOCALEDEF') }}}:
  327. case {{{ cDefine('_SC_2_SW_DEV') }}}:
  328. case {{{ cDefine('_SC_2_VERSION') }}}:
  329. case {{{ cDefine('_SC_THREAD_PRIORITY_SCHEDULING') }}}:
  330. return 200809;
  331. case {{{ cDefine('_SC_MQ_OPEN_MAX') }}}:
  332. case {{{ cDefine('_SC_XOPEN_STREAMS') }}}:
  333. case {{{ cDefine('_SC_XBS5_LP64_OFF64') }}}:
  334. case {{{ cDefine('_SC_XBS5_LPBIG_OFFBIG') }}}:
  335. case {{{ cDefine('_SC_AIO_LISTIO_MAX') }}}:
  336. case {{{ cDefine('_SC_AIO_MAX') }}}:
  337. case {{{ cDefine('_SC_SPORADIC_SERVER') }}}:
  338. case {{{ cDefine('_SC_THREAD_SPORADIC_SERVER') }}}:
  339. case {{{ cDefine('_SC_TRACE') }}}:
  340. case {{{ cDefine('_SC_TRACE_EVENT_FILTER') }}}:
  341. case {{{ cDefine('_SC_TRACE_EVENT_NAME_MAX') }}}:
  342. case {{{ cDefine('_SC_TRACE_INHERIT') }}}:
  343. case {{{ cDefine('_SC_TRACE_LOG') }}}:
  344. case {{{ cDefine('_SC_TRACE_NAME_MAX') }}}:
  345. case {{{ cDefine('_SC_TRACE_SYS_MAX') }}}:
  346. case {{{ cDefine('_SC_TRACE_USER_EVENT_MAX') }}}:
  347. case {{{ cDefine('_SC_TYPED_MEMORY_OBJECTS') }}}:
  348. case {{{ cDefine('_SC_V6_LP64_OFF64') }}}:
  349. case {{{ cDefine('_SC_V6_LPBIG_OFFBIG') }}}:
  350. case {{{ cDefine('_SC_2_FORT_DEV') }}}:
  351. case {{{ cDefine('_SC_2_FORT_RUN') }}}:
  352. case {{{ cDefine('_SC_2_PBS') }}}:
  353. case {{{ cDefine('_SC_2_PBS_ACCOUNTING') }}}:
  354. case {{{ cDefine('_SC_2_PBS_CHECKPOINT') }}}:
  355. case {{{ cDefine('_SC_2_PBS_LOCATE') }}}:
  356. case {{{ cDefine('_SC_2_PBS_MESSAGE') }}}:
  357. case {{{ cDefine('_SC_2_PBS_TRACK') }}}:
  358. case {{{ cDefine('_SC_2_UPE') }}}:
  359. case {{{ cDefine('_SC_THREAD_THREADS_MAX') }}}:
  360. case {{{ cDefine('_SC_SEM_NSEMS_MAX') }}}:
  361. case {{{ cDefine('_SC_SYMLOOP_MAX') }}}:
  362. case {{{ cDefine('_SC_TIMER_MAX') }}}:
  363. return -1;
  364. case {{{ cDefine('_SC_V6_ILP32_OFF32') }}}:
  365. case {{{ cDefine('_SC_V6_ILP32_OFFBIG') }}}:
  366. case {{{ cDefine('_SC_JOB_CONTROL') }}}:
  367. case {{{ cDefine('_SC_REGEXP') }}}:
  368. case {{{ cDefine('_SC_SAVED_IDS') }}}:
  369. case {{{ cDefine('_SC_SHELL') }}}:
  370. case {{{ cDefine('_SC_XBS5_ILP32_OFF32') }}}:
  371. case {{{ cDefine('_SC_XBS5_ILP32_OFFBIG') }}}:
  372. case {{{ cDefine('_SC_XOPEN_CRYPT') }}}:
  373. case {{{ cDefine('_SC_XOPEN_ENH_I18N') }}}:
  374. case {{{ cDefine('_SC_XOPEN_LEGACY') }}}:
  375. case {{{ cDefine('_SC_XOPEN_REALTIME') }}}:
  376. case {{{ cDefine('_SC_XOPEN_REALTIME_THREADS') }}}:
  377. case {{{ cDefine('_SC_XOPEN_SHM') }}}:
  378. case {{{ cDefine('_SC_XOPEN_UNIX') }}}:
  379. return 1;
  380. case {{{ cDefine('_SC_THREAD_KEYS_MAX') }}}:
  381. case {{{ cDefine('_SC_IOV_MAX') }}}:
  382. case {{{ cDefine('_SC_GETGR_R_SIZE_MAX') }}}:
  383. case {{{ cDefine('_SC_GETPW_R_SIZE_MAX') }}}:
  384. case {{{ cDefine('_SC_OPEN_MAX') }}}:
  385. return 1024;
  386. case {{{ cDefine('_SC_RTSIG_MAX') }}}:
  387. case {{{ cDefine('_SC_EXPR_NEST_MAX') }}}:
  388. case {{{ cDefine('_SC_TTY_NAME_MAX') }}}:
  389. return 32;
  390. case {{{ cDefine('_SC_ATEXIT_MAX') }}}:
  391. case {{{ cDefine('_SC_DELAYTIMER_MAX') }}}:
  392. case {{{ cDefine('_SC_SEM_VALUE_MAX') }}}:
  393. return 2147483647;
  394. case {{{ cDefine('_SC_SIGQUEUE_MAX') }}}:
  395. case {{{ cDefine('_SC_CHILD_MAX') }}}:
  396. return 47839;
  397. case {{{ cDefine('_SC_BC_SCALE_MAX') }}}:
  398. case {{{ cDefine('_SC_BC_BASE_MAX') }}}:
  399. return 99;
  400. case {{{ cDefine('_SC_LINE_MAX') }}}:
  401. case {{{ cDefine('_SC_BC_DIM_MAX') }}}:
  402. return 2048;
  403. case {{{ cDefine('_SC_ARG_MAX') }}}: return 2097152;
  404. case {{{ cDefine('_SC_NGROUPS_MAX') }}}: return 65536;
  405. case {{{ cDefine('_SC_MQ_PRIO_MAX') }}}: return 32768;
  406. case {{{ cDefine('_SC_RE_DUP_MAX') }}}: return 32767;
  407. case {{{ cDefine('_SC_THREAD_STACK_MIN') }}}: return 16384;
  408. case {{{ cDefine('_SC_BC_STRING_MAX') }}}: return 1000;
  409. case {{{ cDefine('_SC_XOPEN_VERSION') }}}: return 700;
  410. case {{{ cDefine('_SC_LOGIN_NAME_MAX') }}}: return 256;
  411. case {{{ cDefine('_SC_COLL_WEIGHTS_MAX') }}}: return 255;
  412. case {{{ cDefine('_SC_CLK_TCK') }}}: return 100;
  413. case {{{ cDefine('_SC_HOST_NAME_MAX') }}}: return 64;
  414. case {{{ cDefine('_SC_AIO_PRIO_DELTA_MAX') }}}: return 20;
  415. case {{{ cDefine('_SC_STREAM_MAX') }}}: return 16;
  416. case {{{ cDefine('_SC_TZNAME_MAX') }}}: return 6;
  417. case {{{ cDefine('_SC_THREAD_DESTRUCTOR_ITERATIONS') }}}: return 4;
  418. case {{{ cDefine('_SC_NPROCESSORS_ONLN') }}}: {
  419. if (typeof navigator === 'object') return navigator['hardwareConcurrency'] || 1;
  420. return 1;
  421. }
  422. }
  423. setErrNo({{{ cDefine('EINVAL') }}});
  424. return -1;
  425. },
  426. emscripten_get_heap_size: function() {
  427. return HEAPU8.length;
  428. },
  429. emscripten_get_sbrk_ptr__asm: true,
  430. emscripten_get_sbrk_ptr__sig: 'i',
  431. emscripten_get_sbrk_ptr: function() {
  432. return {{{ DYNAMICTOP_PTR }}};
  433. },
  434. #if ABORTING_MALLOC && !ALLOW_MEMORY_GROWTH
  435. $abortOnCannotGrowMemory: function(requestedSize) {
  436. #if ASSERTIONS
  437. #if WASM
  438. abort('Cannot enlarge memory arrays to size ' + requestedSize + ' bytes (OOM). Either (1) compile with -s INITIAL_MEMORY=X with X higher than the current value ' + HEAP8.length + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ');
  439. #else
  440. abort('Cannot enlarge memory arrays to size ' + requestedSize + ' bytes (OOM). Either (1) compile with -s INITIAL_MEMORY=X with X higher than the current value ' + HEAP8.length + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.INITIAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ');
  441. #endif
  442. #else
  443. abort('OOM');
  444. #endif
  445. },
  446. #endif
  447. #if TEST_MEMORY_GROWTH_FAILS
  448. $emscripten_realloc_buffer: function(size) {
  449. return false;
  450. },
  451. #else
  452. // Grows the asm.js/wasm heap to the given byte size, and updates both JS and asm.js/wasm side views to the buffer.
  453. // Returns 1 on success, or undefined if growing failed.
  454. $emscripten_realloc_buffer: function(size) {
  455. #if MEMORYPROFILER
  456. var oldHeapSize = buffer.byteLength;
  457. #endif
  458. try {
  459. #if WASM
  460. // round size grow request up to wasm page size (fixed 64KB per spec)
  461. wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16); // .grow() takes a delta compared to the previous size
  462. updateGlobalBufferAndViews(wasmMemory.buffer);
  463. #else // asm.js:
  464. var newBuffer = new ArrayBuffer(size);
  465. if (newBuffer.byteLength != size) return /*undefined, allocation did not succeed*/;
  466. new Int8Array(newBuffer).set(/**@type{!Int8Array}*/(HEAP8));
  467. _emscripten_replace_memory(newBuffer);
  468. updateGlobalBufferAndViews(newBuffer);
  469. #endif
  470. #if MEMORYPROFILER
  471. if (typeof emscriptenMemoryProfiler !== 'undefined') {
  472. emscriptenMemoryProfiler.onMemoryResize(oldHeapSize, buffer.byteLength);
  473. }
  474. #endif
  475. return 1 /*success*/;
  476. } catch(e) {
  477. #if ASSERTIONS
  478. console.error('emscripten_realloc_buffer: Attempted to grow heap from ' + buffer.byteLength + ' bytes to ' + size + ' bytes, but got error: ' + e);
  479. #endif
  480. }
  481. },
  482. #endif // ~TEST_MEMORY_GROWTH_FAILS
  483. emscripten_resize_heap__deps: ['emscripten_get_heap_size'
  484. #if ASSERTIONS == 2
  485. , 'emscripten_get_now'
  486. #endif
  487. #if ABORTING_MALLOC && !ALLOW_MEMORY_GROWTH
  488. , '$abortOnCannotGrowMemory'
  489. #endif
  490. #if ALLOW_MEMORY_GROWTH
  491. , '$emscripten_realloc_buffer'
  492. #endif
  493. ],
  494. emscripten_resize_heap: function(requestedSize) {
  495. requestedSize = requestedSize >>> 0;
  496. #if ALLOW_MEMORY_GROWTH == 0
  497. #if ABORTING_MALLOC
  498. abortOnCannotGrowMemory(requestedSize);
  499. #else
  500. return false; // malloc will report failure
  501. #endif // ABORTING_MALLOC
  502. #else // ALLOW_MEMORY_GROWTH == 0
  503. var oldSize = _emscripten_get_heap_size();
  504. // With pthreads, races can happen (another thread might increase the size in between), so return a failure, and let the caller retry.
  505. #if USE_PTHREADS
  506. if (requestedSize <= oldSize) {
  507. return false;
  508. }
  509. #endif // USE_PTHREADS
  510. #if ASSERTIONS && !USE_PTHREADS
  511. assert(requestedSize > oldSize);
  512. #endif
  513. #if EMSCRIPTEN_TRACING
  514. // Report old layout one last time
  515. _emscripten_trace_report_memory_layout();
  516. #endif
  517. var PAGE_MULTIPLE = {{{ getMemoryPageSize() }}};
  518. // Memory resize rules:
  519. // 1. When resizing, always produce a resized heap that is at least 16MB (to avoid tiny heap sizes receiving lots of repeated resizes at startup)
  520. // 2. Always increase heap size to at least the requested size, rounded up to next page multiple.
  521. // 3a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap geometrically: increase the heap size according to
  522. // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%),
  523. // At most overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
  524. // 3b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap linearly: increase the heap size by at least MEMORY_GROWTH_LINEAR_STEP bytes.
  525. // 4. Max size for the heap is capped at 2048MB-PAGE_MULTIPLE, or by MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
  526. // 5. If we were unable to allocate as much memory, it may be due to over-eager decision to excessively reserve due to (3) above.
  527. // Hence if an allocation fails, cut down on the amount of excess growth, in an attempt to succeed to perform a smaller allocation.
  528. #if MAXIMUM_MEMORY != -1
  529. // A limit was set for how much we can grow. We should not exceed that
  530. // (the wasm binary specifies it, so if we tried, we'd fail anyhow).
  531. var maxHeapSize = {{{ MAXIMUM_MEMORY }}};
  532. #else
  533. var maxHeapSize = {{{ CAN_ADDRESS_2GB ? 4294967296 : 2147483648 }}} - PAGE_MULTIPLE;
  534. #endif
  535. if (requestedSize > maxHeapSize) {
  536. #if ASSERTIONS
  537. err('Cannot enlarge memory, asked to go up to ' + requestedSize + ' bytes, but the limit is ' + maxHeapSize + ' bytes!');
  538. #endif
  539. return false;
  540. }
  541. #if USE_ASAN
  542. // One byte of ASan's shadow memory shadows 8 bytes of real memory. Shadow memory area has a fixed size,
  543. // so do not allow resizing past that limit.
  544. maxHeapSize = Math.min(maxHeapSize, {{{ 8 * ASAN_SHADOW_SIZE }}});
  545. if (requestedSize > maxHeapSize) {
  546. #if ASSERTIONS
  547. err('Failed to grow the heap from ' + oldSize + ', as we reached the limit of our shadow memory. Increase ASAN_SHADOW_SIZE.');
  548. #endif
  549. return false;
  550. }
  551. #endif
  552. var minHeapSize = 16777216;
  553. // Loop through potential heap size increases. If we attempt a too eager reservation that fails, cut down on the
  554. // attempted size and reserve a smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
  555. for(var cutDown = 1; cutDown <= 4; cutDown *= 2) {
  556. #if MEMORY_GROWTH_LINEAR_STEP == -1
  557. var overGrownHeapSize = oldSize * (1 + {{{ MEMORY_GROWTH_GEOMETRIC_STEP }}} / cutDown); // ensure geometric growth
  558. #if MEMORY_GROWTH_GEOMETRIC_CAP
  559. // but limit overreserving (default to capping at +96MB overgrowth at most)
  560. overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + {{{ MEMORY_GROWTH_GEOMETRIC_CAP }}} );
  561. #endif
  562. #else
  563. var overGrownHeapSize = oldSize + {{{ MEMORY_GROWTH_LINEAR_STEP }}} / cutDown; // ensure linear growth
  564. #endif
  565. var newSize = Math.min(maxHeapSize, alignUp(Math.max(minHeapSize, requestedSize, overGrownHeapSize), PAGE_MULTIPLE));
  566. #if ASSERTIONS == 2
  567. var t0 = _emscripten_get_now();
  568. #endif
  569. var replacement = emscripten_realloc_buffer(newSize);
  570. #if ASSERTIONS == 2
  571. var t1 = _emscripten_get_now();
  572. console.log('Heap resize call from ' + oldSize + ' to ' + newSize + ' took ' + (t1 - t0) + ' msecs. Success: ' + !!replacement);
  573. #endif
  574. if (replacement) {
  575. #if ASSERTIONS && (!WASM || WASM2JS)
  576. err('Warning: Enlarging memory arrays, this is not fast! ' + [oldSize, newSize]);
  577. #endif
  578. #if EMSCRIPTEN_TRACING
  579. _emscripten_trace_js_log_message("Emscripten", "Enlarging memory arrays from " + oldSize + " to " + newSize);
  580. // And now report the new layout
  581. _emscripten_trace_report_memory_layout();
  582. #endif
  583. return true;
  584. }
  585. }
  586. #if ASSERTIONS
  587. err('Failed to grow the heap from ' + oldSize + ' bytes to ' + newSize + ' bytes, not enough memory!');
  588. #endif
  589. return false;
  590. #endif // ALLOW_MEMORY_GROWTH
  591. },
  592. // Called after wasm grows memory. At that time we need to update the views.
  593. // Without this notification, we'd need to check the buffer in JS every time
  594. // we return from any wasm, which adds overhead. See
  595. // https://github.com/WebAssembly/WASI/issues/82
  596. emscripten_notify_memory_growth: function(memoryIndex) {
  597. #if ASSERTIONS
  598. assert(memoryIndex == 0);
  599. #endif
  600. updateGlobalBufferAndViews(wasmMemory.buffer);
  601. },
  602. system__deps: ['$setErrNo'],
  603. system: function(command) {
  604. #if ENVIRONMENT_MAY_BE_NODE
  605. if (ENVIRONMENT_IS_NODE) {
  606. if (!command) return 1; // shell is available
  607. var cmdstr = UTF8ToString(command);
  608. if (!cmdstr.length) return 0; // this is what glibc seems to do (shell works test?)
  609. var cp = require('child_process');
  610. var ret = cp.spawnSync(cmdstr, [], {shell:true, stdio:'inherit'});
  611. var _W_EXITCODE = function(ret, sig) {
  612. return ((ret) << 8 | (sig));
  613. }
  614. // this really only can happen if process is killed by signal
  615. if (ret.status === null) {
  616. // sadly node doesn't expose such function
  617. var signalToNumber = function(sig) {
  618. // implement only the most common ones, and fallback to SIGINT
  619. switch (sig) {
  620. case 'SIGHUP': return 1;
  621. case 'SIGINT': return 2;
  622. case 'SIGQUIT': return 3;
  623. case 'SIGFPE': return 8;
  624. case 'SIGKILL': return 9;
  625. case 'SIGALRM': return 14;
  626. case 'SIGTERM': return 15;
  627. }
  628. return 2; // SIGINT
  629. }
  630. return _W_EXITCODE(0, signalToNumber(ret.signal));
  631. }
  632. return _W_EXITCODE(ret.status, 0);
  633. }
  634. #endif // ENVIRONMENT_MAY_BE_NODE
  635. // int system(const char *command);
  636. // http://pubs.opengroup.org/onlinepubs/000095399/functions/system.html
  637. // Can't call external programs.
  638. if (!command) return 0; // no shell available
  639. setErrNo({{{ cDefine('EAGAIN') }}});
  640. return -1;
  641. },
  642. // ==========================================================================
  643. // stdlib.h
  644. // ==========================================================================
  645. abs: 'Math_abs',
  646. labs: 'Math_abs',
  647. _ZSt9terminatev__deps: ['exit'],
  648. _ZSt9terminatev: function() {
  649. _exit(-1234);
  650. },
  651. #if MINIMAL_RUNTIME && !EXIT_RUNTIME
  652. atexit: function(){},
  653. __cxa_atexit: function(){},
  654. __cxa_thread_atexit: function(){},
  655. __cxa_thread_atexit_impl: function(){},
  656. #else
  657. atexit__proxy: 'sync',
  658. atexit__sig: 'iii',
  659. atexit: function(func, arg) {
  660. #if ASSERTIONS
  661. #if EXIT_RUNTIME == 0
  662. warnOnce('atexit() called, but EXIT_RUNTIME is not set, so atexits() will not be called. set EXIT_RUNTIME to 1 (see the FAQ)');
  663. #endif
  664. #endif
  665. __ATEXIT__.unshift({ func: func, arg: arg });
  666. },
  667. __cxa_atexit: 'atexit',
  668. // used in rust, clang when doing thread_local statics
  669. __cxa_thread_atexit: 'atexit',
  670. __cxa_thread_atexit_impl: 'atexit',
  671. #endif
  672. // TODO: There are currently two abort() functions that get imported to asm module scope: the built-in runtime function abort(),
  673. // and this function _abort(). Remove one of these, importing two functions for the same purpose is wasteful.
  674. abort: function() {
  675. #if MINIMAL_RUNTIME
  676. // In MINIMAL_RUNTIME the module object does not exist, so its behavior to abort is to throw directly.
  677. throw 'abort';
  678. #else
  679. abort();
  680. #endif
  681. },
  682. // This object can be modified by the user during startup, which affects
  683. // the initial values of the environment accessible by getenv. (This works
  684. // in both fastcomp and upstream.
  685. $ENV: {},
  686. #if !WASM_BACKEND
  687. // This implementation of environ/getenv/etc. is used for fastcomp, due
  688. // to limitations in the system libraries (we can't easily add a global
  689. // ctor to create the environment without it always being linked in with
  690. // libc).
  691. __buildEnvironment__deps: ['$ENV', '_getExecutableName'],
  692. __buildEnvironment: function(environ) {
  693. // WARNING: Arbitrary limit!
  694. var MAX_ENV_VALUES = 64;
  695. var TOTAL_ENV_SIZE = 1024;
  696. // Statically allocate memory for the environment.
  697. var poolPtr;
  698. var envPtr;
  699. if (!___buildEnvironment.called) {
  700. ___buildEnvironment.called = true;
  701. // Set default values. Use string keys for Closure Compiler compatibility.
  702. ENV['USER'] = 'web_user';
  703. ENV['LOGNAME'] = 'web_user';
  704. ENV['PATH'] = '/';
  705. ENV['PWD'] = '/';
  706. ENV['HOME'] = '/home/web_user';
  707. // Browser language detection #8751
  708. ENV['LANG'] = ((typeof navigator === 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8';
  709. ENV['_'] = __getExecutableName();
  710. // Allocate memory.
  711. #if !MINIMAL_RUNTIME // TODO: environment support in MINIMAL_RUNTIME
  712. poolPtr = getMemory(TOTAL_ENV_SIZE);
  713. envPtr = getMemory(MAX_ENV_VALUES * {{{ Runtime.POINTER_SIZE }}});
  714. {{{ makeSetValue('envPtr', '0', 'poolPtr', 'i8*') }}};
  715. {{{ makeSetValue('environ', 0, 'envPtr', 'i8*') }}};
  716. #endif
  717. } else {
  718. envPtr = {{{ makeGetValue('environ', '0', 'i8**') }}};
  719. poolPtr = {{{ makeGetValue('envPtr', '0', 'i8*') }}};
  720. }
  721. // Collect key=value lines.
  722. var strings = [];
  723. var totalSize = 0;
  724. for (var key in ENV) {
  725. if (typeof ENV[key] === 'string') {
  726. var line = key + '=' + ENV[key];
  727. strings.push(line);
  728. totalSize += line.length;
  729. }
  730. }
  731. if (totalSize > TOTAL_ENV_SIZE) {
  732. throw new Error('Environment size exceeded TOTAL_ENV_SIZE!');
  733. }
  734. // Make new.
  735. var ptrSize = {{{ Runtime.getNativeTypeSize('i8*') }}};
  736. for (var i = 0; i < strings.length; i++) {
  737. var line = strings[i];
  738. writeAsciiToMemory(line, poolPtr);
  739. {{{ makeSetValue('envPtr', 'i * ptrSize', 'poolPtr', 'i8*') }}};
  740. poolPtr += line.length + 1;
  741. }
  742. {{{ makeSetValue('envPtr', 'strings.length * ptrSize', '0', 'i8*') }}};
  743. },
  744. getenv__deps: ['$ENV',
  745. #if MINIMAL_RUNTIME
  746. '$allocateUTF8',
  747. #endif
  748. ],
  749. getenv__proxy: 'sync',
  750. getenv__sig: 'ii',
  751. getenv: function(name) {
  752. // char *getenv(const char *name);
  753. // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html
  754. if (name === 0) return 0;
  755. name = UTF8ToString(name);
  756. if (!ENV.hasOwnProperty(name)) return 0;
  757. if (_getenv.ret) _free(_getenv.ret);
  758. _getenv.ret = allocateUTF8(ENV[name]);
  759. return _getenv.ret;
  760. },
  761. clearenv__deps: ['$ENV', '__buildEnvironment'],
  762. clearenv__proxy: 'sync',
  763. clearenv__sig: 'i',
  764. clearenv: function() {
  765. // int clearenv (void);
  766. // http://www.gnu.org/s/hello/manual/libc/Environment-Access.html#index-clearenv-3107
  767. ENV = {};
  768. ___buildEnvironment(__get_environ());
  769. return 0;
  770. },
  771. setenv__deps: ['$ENV', '__buildEnvironment', '$setErrNo'],
  772. setenv__proxy: 'sync',
  773. setenv__sig: 'iiii',
  774. setenv: function(envname, envval, overwrite) {
  775. // int setenv(const char *envname, const char *envval, int overwrite);
  776. // http://pubs.opengroup.org/onlinepubs/009695399/functions/setenv.html
  777. if (envname === 0) {
  778. setErrNo({{{ cDefine('EINVAL') }}});
  779. return -1;
  780. }
  781. var name = UTF8ToString(envname);
  782. var val = UTF8ToString(envval);
  783. if (name === '' || name.indexOf('=') !== -1) {
  784. setErrNo({{{ cDefine('EINVAL') }}});
  785. return -1;
  786. }
  787. if (ENV.hasOwnProperty(name) && !overwrite) return 0;
  788. ENV[name] = val;
  789. ___buildEnvironment(__get_environ());
  790. return 0;
  791. },
  792. unsetenv__deps: ['$ENV', '__buildEnvironment', '$setErrNo'],
  793. unsetenv__proxy: 'sync',
  794. unsetenv__sig: 'ii',
  795. unsetenv: function(name) {
  796. // int unsetenv(const char *name);
  797. // http://pubs.opengroup.org/onlinepubs/009695399/functions/unsetenv.html
  798. if (name === 0) {
  799. setErrNo({{{ cDefine('EINVAL') }}});
  800. return -1;
  801. }
  802. name = UTF8ToString(name);
  803. if (name === '' || name.indexOf('=') !== -1) {
  804. setErrNo({{{ cDefine('EINVAL') }}});
  805. return -1;
  806. }
  807. if (ENV.hasOwnProperty(name)) {
  808. delete ENV[name];
  809. ___buildEnvironment(__get_environ());
  810. }
  811. return 0;
  812. },
  813. putenv__deps: ['$ENV', '__buildEnvironment', '$setErrNo'],
  814. putenv__proxy: 'sync',
  815. putenv__sig: 'ii',
  816. putenv: function(string) {
  817. // int putenv(char *string);
  818. // http://pubs.opengroup.org/onlinepubs/009695399/functions/putenv.html
  819. // WARNING: According to the standard (and the glibc implementation), the
  820. // string is taken by reference so future changes are reflected.
  821. // We copy it instead, possibly breaking some uses.
  822. if (string === 0) {
  823. setErrNo({{{ cDefine('EINVAL') }}});
  824. return -1;
  825. }
  826. string = UTF8ToString(string);
  827. var splitPoint = string.indexOf('=')
  828. if (string === '' || string.indexOf('=') === -1) {
  829. setErrNo({{{ cDefine('EINVAL') }}});
  830. return -1;
  831. }
  832. var name = string.slice(0, splitPoint);
  833. var value = string.slice(splitPoint + 1);
  834. if (!(name in ENV) || ENV[name] !== value) {
  835. ENV[name] = value;
  836. ___buildEnvironment(__get_environ());
  837. }
  838. return 0;
  839. },
  840. #endif
  841. getloadavg: function(loadavg, nelem) {
  842. // int getloadavg(double loadavg[], int nelem);
  843. // http://linux.die.net/man/3/getloadavg
  844. var limit = Math.min(nelem, 3);
  845. var doubleSize = {{{ Runtime.getNativeTypeSize('double') }}};
  846. for (var i = 0; i < limit; i++) {
  847. {{{ makeSetValue('loadavg', 'i * doubleSize', '0.1', 'double') }}};
  848. }
  849. return limit;
  850. },
  851. // ==========================================================================
  852. // string.h
  853. // ==========================================================================
  854. memcpy__inline: function(dest, src, num, align) {
  855. var ret = '';
  856. ret += makeCopyValues(dest, src, num, 'null', null, align);
  857. return ret;
  858. },
  859. #if MIN_CHROME_VERSION < 45 || MIN_EDGE_VERSION < 14 || MIN_FIREFOX_VERSION < 34 || MIN_IE_VERSION != TARGET_NOT_SUPPORTED || MIN_SAFARI_VERSION < 100101 || STANDALONE_WASM
  860. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/copyWithin lists browsers that support TypedArray.prototype.copyWithin, but it
  861. // has outdated information for Safari, saying it would not support it.
  862. // https://github.com/WebKit/webkit/commit/24a800eea4d82d6d595cdfec69d0f68e733b5c52#diff-c484911d8df319ba75fce0d8e7296333R1 suggests support was added on Aug 28, 2015.
  863. // Manual testing suggests:
  864. // Safari/601.1 Version/9.0 on iPhone 4s with iOS 9.3.6 (released September 30, 2015) does not support copyWithin.
  865. // but the following systems do:
  866. // AppleWebKit/602.2.14 Safari/602.1 Version/10.0 Mobile/14B100 iPhone OS 10_1_1 on iPhone 5s with iOS 10.1.1 (released October 31, 2016)
  867. // AppleWebKit/603.3.8 Safari/602.1 Version/10.0 on iPhone 5 with iOS 10.3.4 (released July 22, 2019)
  868. // AppleWebKit/605.1.15 iPhone OS 12_3_1 Version/12.1.1 Safari/604.1 on iPhone SE with iOS 12.3.1
  869. // AppleWebKit/605.1.15 Safari/604.1 Version/13.0.4 iPhone OS 13_3 on iPhone 6s with iOS 13.3
  870. // AppleWebKit/605.1.15 Version/13.0.3 Intel Mac OS X 10_15_1 on Safari 13.0.3 (15608.3.10.1.4) on macOS Catalina 10.15.1
  871. // Hence the support status of .copyWithin() for Safari version range [10.0.0, 10.1.0] is unknown.
  872. emscripten_memcpy_big__import: true,
  873. emscripten_memcpy_big: '= Uint8Array.prototype.copyWithin\n' +
  874. ' ? function(dest, src, num) { HEAPU8.copyWithin(dest, src, src + num); }\n' +
  875. ' : function(dest, src, num) { HEAPU8.set(HEAPU8.subarray(src, src+num), dest); }\n',
  876. #else
  877. emscripten_memcpy_big: function(dest, src, num) {
  878. HEAPU8.copyWithin(dest, src, src + num);
  879. },
  880. #endif
  881. #if !WASM_BACKEND
  882. memcpy__asm: true,
  883. memcpy__sig: 'iiii',
  884. memcpy__deps: ['emscripten_memcpy_big', 'Int8Array', 'Int32Array'],
  885. memcpy: function(dest, src, num) {
  886. dest = dest|0; src = src|0; num = num|0;
  887. var ret = 0;
  888. var aligned_dest_end = 0;
  889. var block_aligned_dest_end = 0;
  890. var dest_end = 0;
  891. // Test against a benchmarked cutoff limit for when HEAPU8.copyWithin() becomes faster to use.
  892. if ((num|0) >= 512) {
  893. _emscripten_memcpy_big(dest|0, src|0, num|0)|0;
  894. return dest|0;
  895. }
  896. ret = dest|0;
  897. dest_end = (dest + num)|0;
  898. if ((dest&3) == (src&3)) {
  899. // The initial unaligned < 4-byte front.
  900. while (dest & 3) {
  901. if ((num|0) == 0) return ret|0;
  902. {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}};
  903. dest = (dest+1)|0;
  904. src = (src+1)|0;
  905. num = (num-1)|0;
  906. }
  907. aligned_dest_end = (dest_end & -4)|0;
  908. #if FAST_UNROLLED_MEMCPY_AND_MEMSET
  909. block_aligned_dest_end = (aligned_dest_end - 64)|0;
  910. while ((dest|0) <= (block_aligned_dest_end|0) ) {
  911. {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i32'), 'i32') }}};
  912. {{{ makeSetValueAsm('dest', 4, makeGetValueAsm('src', 4, 'i32'), 'i32') }}};
  913. {{{ makeSetValueAsm('dest', 8, makeGetValueAsm('src', 8, 'i32'), 'i32') }}};
  914. {{{ makeSetValueAsm('dest', 12, makeGetValueAsm('src', 12, 'i32'), 'i32') }}};
  915. {{{ makeSetValueAsm('dest', 16, makeGetValueAsm('src', 16, 'i32'), 'i32') }}};
  916. {{{ makeSetValueAsm('dest', 20, makeGetValueAsm('src', 20, 'i32'), 'i32') }}};
  917. {{{ makeSetValueAsm('dest', 24, makeGetValueAsm('src', 24, 'i32'), 'i32') }}};
  918. {{{ makeSetValueAsm('dest', 28, makeGetValueAsm('src', 28, 'i32'), 'i32') }}};
  919. {{{ makeSetValueAsm('dest', 32, makeGetValueAsm('src', 32, 'i32'), 'i32') }}};
  920. {{{ makeSetValueAsm('dest', 36, makeGetValueAsm('src', 36, 'i32'), 'i32') }}};
  921. {{{ makeSetValueAsm('dest', 40, makeGetValueAsm('src', 40, 'i32'), 'i32') }}};
  922. {{{ makeSetValueAsm('dest', 44, makeGetValueAsm('src', 44, 'i32'), 'i32') }}};
  923. {{{ makeSetValueAsm('dest', 48, makeGetValueAsm('src', 48, 'i32'), 'i32') }}};
  924. {{{ makeSetValueAsm('dest', 52, makeGetValueAsm('src', 52, 'i32'), 'i32') }}};
  925. {{{ makeSetValueAsm('dest', 56, makeGetValueAsm('src', 56, 'i32'), 'i32') }}};
  926. {{{ makeSetValueAsm('dest', 60, makeGetValueAsm('src', 60, 'i32'), 'i32') }}};
  927. dest = (dest+64)|0;
  928. src = (src+64)|0;
  929. }
  930. #endif
  931. while ((dest|0) < (aligned_dest_end|0) ) {
  932. {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i32'), 'i32') }}};
  933. dest = (dest+4)|0;
  934. src = (src+4)|0;
  935. }
  936. } else {
  937. // In the unaligned copy case, unroll a bit as well.
  938. aligned_dest_end = (dest_end - 4)|0;
  939. while ((dest|0) < (aligned_dest_end|0) ) {
  940. {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}};
  941. {{{ makeSetValueAsm('dest', 1, makeGetValueAsm('src', 1, 'i8'), 'i8') }}};
  942. {{{ makeSetValueAsm('dest', 2, makeGetValueAsm('src', 2, 'i8'), 'i8') }}};
  943. {{{ makeSetValueAsm('dest', 3, makeGetValueAsm('src', 3, 'i8'), 'i8') }}};
  944. dest = (dest+4)|0;
  945. src = (src+4)|0;
  946. }
  947. }
  948. // The remaining unaligned < 4 byte tail.
  949. while ((dest|0) < (dest_end|0)) {
  950. {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}};
  951. dest = (dest+1)|0;
  952. src = (src+1)|0;
  953. }
  954. return ret|0;
  955. },
  956. memmove__sig: 'iiii',
  957. memmove__asm: true,
  958. memmove__deps: ['memcpy'],
  959. memmove: function(dest, src, num) {
  960. dest = dest|0; src = src|0; num = num|0;
  961. var ret = 0;
  962. if (((src|0) < (dest|0)) & ((dest|0) < ((src + num)|0))) {
  963. // Unlikely case: Copy backwards in a safe manner
  964. ret = dest;
  965. src = (src + num)|0;
  966. dest = (dest + num)|0;
  967. while ((num|0) > 0) {
  968. dest = (dest - 1)|0;
  969. src = (src - 1)|0;
  970. num = (num - 1)|0;
  971. {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}};
  972. }
  973. dest = ret;
  974. } else {
  975. _memcpy(dest, src, num) | 0;
  976. }
  977. return dest | 0;
  978. },
  979. memset__inline: function(ptr, value, num, align) {
  980. return makeSetValues(ptr, 0, value, 'null', num, align);
  981. },
  982. memset__sig: 'iiii',
  983. memset__asm: true,
  984. memset__deps: ['Int8Array', 'Int32Array'],
  985. memset: function(ptr, value, num) {
  986. ptr = ptr|0; value = value|0; num = num|0;
  987. var end = 0, aligned_end = 0, block_aligned_end = 0, value4 = 0;
  988. end = (ptr + num)|0;
  989. value = value & 0xff;
  990. if ((num|0) >= 67 /* 64 bytes for an unrolled loop + 3 bytes for unaligned head*/) {
  991. while ((ptr&3) != 0) {
  992. {{{ makeSetValueAsm('ptr', 0, 'value', 'i8') }}};
  993. ptr = (ptr+1)|0;
  994. }
  995. aligned_end = (end & -4)|0;
  996. value4 = value | (value << 8) | (value << 16) | (value << 24);
  997. #if FAST_UNROLLED_MEMCPY_AND_MEMSET
  998. block_aligned_end = (aligned_end - 64)|0;
  999. while((ptr|0) <= (block_aligned_end|0)) {
  1000. {{{ makeSetValueAsm('ptr', 0, 'value4', 'i32') }}};
  1001. {{{ makeSetValueAsm('ptr', 4, 'value4', 'i32') }}};
  1002. {{{ makeSetValueAsm('ptr', 8, 'value4', 'i32') }}};
  1003. {{{ makeSetValueAsm('ptr', 12, 'value4', 'i32') }}};
  1004. {{{ makeSetValueAsm('ptr', 16, 'value4', 'i32') }}};
  1005. {{{ makeSetValueAsm('ptr', 20, 'value4', 'i32') }}};
  1006. {{{ makeSetValueAsm('ptr', 24, 'value4', 'i32') }}};
  1007. {{{ makeSetValueAsm('ptr', 28, 'value4', 'i32') }}};
  1008. {{{ makeSetValueAsm('ptr', 32, 'value4', 'i32') }}};
  1009. {{{ makeSetValueAsm('ptr', 36, 'value4', 'i32') }}};
  1010. {{{ makeSetValueAsm('ptr', 40, 'value4', 'i32') }}};
  1011. {{{ makeSetValueAsm('ptr', 44, 'value4', 'i32') }}};
  1012. {{{ makeSetValueAsm('ptr', 48, 'value4', 'i32') }}};
  1013. {{{ makeSetValueAsm('ptr', 52, 'value4', 'i32') }}};
  1014. {{{ makeSetValueAsm('ptr', 56, 'value4', 'i32') }}};
  1015. {{{ makeSetValueAsm('ptr', 60, 'value4', 'i32') }}};
  1016. ptr = (ptr + 64)|0;
  1017. }
  1018. #endif
  1019. while ((ptr|0) < (aligned_end|0) ) {
  1020. {{{ makeSetValueAsm('ptr', 0, 'value4', 'i32') }}};
  1021. ptr = (ptr+4)|0;
  1022. }
  1023. }
  1024. // The remaining bytes.
  1025. while ((ptr|0) < (end|0)) {
  1026. {{{ makeSetValueAsm('ptr', 0, 'value', 'i8') }}};
  1027. ptr = (ptr+1)|0;
  1028. }
  1029. return (end-num)|0;
  1030. },
  1031. #endif // !WASM_BACKEND
  1032. memcpy__sig: 'iiii',
  1033. memmove__sig: 'iiii',
  1034. memset__sig: 'iiii',
  1035. #if DECLARE_ASM_MODULE_EXPORTS
  1036. llvm_memcpy_i32: 'memcpy',
  1037. llvm_memcpy_i64: 'memcpy',
  1038. llvm_memcpy_p0i8_p0i8_i32: 'memcpy',
  1039. llvm_memcpy_p0i8_p0i8_i64: 'memcpy',
  1040. llvm_memmove_i32: 'memmove',
  1041. llvm_memmove_i64: 'memmove',
  1042. llvm_memmove_p0i8_p0i8_i32: 'memmove',
  1043. llvm_memmove_p0i8_p0i8_i64: 'memmove',
  1044. llvm_memset_i32: 'memset',
  1045. llvm_memset_p0i8_i32: 'memset',
  1046. llvm_memset_p0i8_i64: 'memset',
  1047. #else
  1048. // When DECLARE_ASM_MODULE_EXPORTS==0, cannot alias asm.js functions from non-asm.js
  1049. // functions, so use an intermediate function as a pass-through.
  1050. _memcpy_js__deps: ['memcpy'],
  1051. _memcpy_js__sig: 'iiii',
  1052. _memcpy_js: function(dst, src, num) {
  1053. return _memcpy(dst, src, num);
  1054. },
  1055. _memmove_js__deps: ['memmove'],
  1056. _memmove_js__sig: 'iiii',
  1057. _memmove_js: function(dst, src, num) {
  1058. return _memmove(dst, src, num);
  1059. },
  1060. _memset_js__deps: ['memset'],
  1061. _memset_js__sig: 'iiii',
  1062. _memset_js: function(ptr, value, num) {
  1063. return _memset(ptr, value, num);
  1064. },
  1065. llvm_memcpy_i32: '_memcpy_js',
  1066. llvm_memcpy_i64: '_memcpy_js',
  1067. llvm_memcpy_p0i8_p0i8_i32: '_memcpy_js',
  1068. llvm_memcpy_p0i8_p0i8_i64: '_memcpy_js',
  1069. llvm_memmove_i32: '_memmove_js',
  1070. llvm_memmove_i64: '_memmove_js',
  1071. llvm_memmove_p0i8_p0i8_i32: '_memmove_js',
  1072. llvm_memmove_p0i8_p0i8_i64: '_memmove_js',
  1073. llvm_memset_i32: '_memset_js',
  1074. llvm_memset_p0i8_i32: '_memset_js',
  1075. llvm_memset_p0i8_i64: '_memset_js',
  1076. #endif // ~DECLARE_ASM_MODULE_EXPORTS
  1077. // ==========================================================================
  1078. // GCC/LLVM specifics
  1079. // ==========================================================================
  1080. __builtin_prefetch: function(){},
  1081. // ==========================================================================
  1082. // LLVM specifics
  1083. // ==========================================================================
  1084. llvm_va_start__inline: function(ptr) {
  1085. // varargs - we received a pointer to the varargs as a final 'extra' parameter called 'varrp'
  1086. // 2-word structure: struct { void* start; void* currentOffset; }
  1087. return makeSetValue(ptr, 0, 'varrp', 'void*') + ';' + makeSetValue(ptr, Runtime.QUANTUM_SIZE, 0, 'void*');
  1088. },
  1089. llvm_va_end: function() {},
  1090. llvm_va_copy: function(ppdest, ppsrc) {
  1091. // copy the list start
  1092. {{{ makeCopyValues('ppdest', 'ppsrc', Runtime.QUANTUM_SIZE, 'null', null, 1) }}};
  1093. // copy the list's current offset (will be advanced with each call to va_arg)
  1094. {{{ makeCopyValues('(ppdest+'+Runtime.QUANTUM_SIZE+')', '(ppsrc+'+Runtime.QUANTUM_SIZE+')', Runtime.QUANTUM_SIZE, 'null', null, 1) }}};
  1095. },
  1096. llvm_bswap_i16__asm: true,
  1097. llvm_bswap_i16__sig: 'ii',
  1098. llvm_bswap_i16: function(x) {
  1099. x = x|0;
  1100. return (((x&0xff)<<8) | ((x>>8)&0xff))|0;
  1101. },
  1102. llvm_bswap_i32__asm: true,
  1103. llvm_bswap_i32__sig: 'ii',
  1104. llvm_bswap_i32: function(x) {
  1105. x = x|0;
  1106. return (((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24))|0;
  1107. },
  1108. llvm_bswap_i64__deps: ['llvm_bswap_i32'],
  1109. llvm_bswap_i64: function(l, h) {
  1110. var retl = _llvm_bswap_i32(h)>>>0;
  1111. var reth = _llvm_bswap_i32(l)>>>0;
  1112. {{{ makeStructuralReturn(['retl', 'reth']) }}};
  1113. },
  1114. llvm_ctlz_i8__asm: true,
  1115. llvm_ctlz_i8__sig: 'ii',
  1116. llvm_ctlz_i8__deps: ['Math_clz32'],
  1117. llvm_ctlz_i8: function(x, isZeroUndef) {
  1118. x = x | 0;
  1119. isZeroUndef = isZeroUndef | 0;
  1120. return (Math_clz32(x & 0xff) | 0) - 24 | 0;
  1121. },
  1122. llvm_ctlz_i16__asm: true,
  1123. llvm_ctlz_i16__sig: 'ii',
  1124. llvm_ctlz_i16__deps: ['Math_clz32'],
  1125. llvm_ctlz_i16: function(x, isZeroUndef) {
  1126. x = x | 0;
  1127. isZeroUndef = isZeroUndef | 0;
  1128. return (Math_clz32(x & 0xffff) | 0) - 16 | 0
  1129. },
  1130. llvm_ctlz_i64__asm: true,
  1131. llvm_ctlz_i64__sig: 'iii',
  1132. llvm_ctlz_i64__deps: ['Math_clz32'],
  1133. llvm_ctlz_i64: function(l, h, isZeroUndef) {
  1134. l = l | 0;
  1135. h = h | 0;
  1136. isZeroUndef = isZeroUndef | 0;
  1137. var ret = 0;
  1138. ret = Math_clz32(h) | 0;
  1139. if ((ret | 0) == 32) ret = ret + (Math_clz32(l) | 0) | 0;
  1140. {{{ makeSetTempRet0('0') }}};
  1141. return ret | 0;
  1142. },
  1143. #if WASM == 0 // binaryen will convert these calls to wasm anyhow
  1144. llvm_cttz_i32__asm: true,
  1145. #endif
  1146. llvm_cttz_i32__sig: 'ii',
  1147. llvm_cttz_i32__deps: ['Math_clz32'],
  1148. llvm_cttz_i32: function(x) { // Note: Currently doesn't take isZeroUndef()
  1149. x = x | 0;
  1150. return (x ? (31 - (Math_clz32((x ^ (x - 1))) | 0) | 0) : 32) | 0;
  1151. },
  1152. llvm_cttz_i64__deps: ['llvm_cttz_i32'],
  1153. llvm_cttz_i64: function(l, h) {
  1154. var ret = _llvm_cttz_i32(l);
  1155. if (ret == 32) ret += _llvm_cttz_i32(h);
  1156. {{{ makeStructuralReturn(['ret', '0']) }}};
  1157. },
  1158. llvm_ctpop_i32__asm: true,
  1159. llvm_ctpop_i32__sig: 'ii',
  1160. llvm_ctpop_i32__deps: ['Math_imul'],
  1161. llvm_ctpop_i32: function(x) {
  1162. // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
  1163. // http://bits.stephan-brumme.com/countBits.html
  1164. x = x | 0;
  1165. x = x - ((x >>> 1) & 0x55555555) | 0;
  1166. x = (x & 0x33333333) + ((x >>> 2) & 0x33333333) | 0;
  1167. return (Math_imul((x + (x >>> 4) & 252645135 /* 0xF0F0F0F, but hits uglify parse bug? */), 0x1010101) >>> 24) | 0;
  1168. },
  1169. llvm_ctpop_i64__deps: ['llvm_ctpop_i32'],
  1170. llvm_ctpop_i64__asm: true,
  1171. llvm_ctpop_i64__sig: 'iii',
  1172. llvm_ctpop_i64: function(l, h) {
  1173. l = l | 0;
  1174. h = h | 0;
  1175. return (_llvm_ctpop_i32(l) | 0) + (_llvm_ctpop_i32(h) | 0) | 0;
  1176. },
  1177. llvm_trap: function() {
  1178. abort('trap!');
  1179. },
  1180. llvm_prefetch: function(){},
  1181. __assert_fail: function(condition, filename, line, func) {
  1182. abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
  1183. },
  1184. __assert_func: function(filename, line, func, condition) {
  1185. abort('Assertion failed: ' + (condition ? UTF8ToString(condition) : 'unknown condition') + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
  1186. },
  1187. #if WASM_BACKEND == 0
  1188. setThrew__asm: true,
  1189. setThrew__sig: 'vii',
  1190. setThrew: function(threw, value) {
  1191. threw = threw|0;
  1192. value = value|0;
  1193. if ((__THREW__|0) == 0) {
  1194. __THREW__ = threw;
  1195. threwValue = value;
  1196. }
  1197. },
  1198. #endif
  1199. terminate__sig: 'vi',
  1200. terminate: '__cxa_call_unexpected',
  1201. __gxx_personality_v0: function() {
  1202. },
  1203. __gcc_personality_v0: function() {
  1204. },
  1205. #if MINIMAL_RUNTIME && !WASM_BACKEND
  1206. llvm_stacksave__deps: ['$stackSave'],
  1207. #endif
  1208. llvm_stacksave: function() {
  1209. var self = _llvm_stacksave;
  1210. if (!self.LLVM_SAVEDSTACKS) {
  1211. self.LLVM_SAVEDSTACKS = [];
  1212. }
  1213. self.LLVM_SAVEDSTACKS.push(stackSave());
  1214. return self.LLVM_SAVEDSTACKS.length-1;
  1215. },
  1216. #if MINIMAL_RUNTIME && !WASM_BACKEND
  1217. llvm_stackrestore__deps: ['$stackRestore'],
  1218. #endif
  1219. llvm_stackrestore: function(p) {
  1220. var self = _llvm_stacksave;
  1221. var ret = self.LLVM_SAVEDSTACKS[p];
  1222. self.LLVM_SAVEDSTACKS.splice(p, 1);
  1223. stackRestore(ret);
  1224. },
  1225. #if MINIMAL_RUNTIME
  1226. #if WASM_BACKEND == 0
  1227. $abortStackOverflow__deps: ['$stackSave'],
  1228. #endif
  1229. $abortStackOverflow__import: true,
  1230. $abortStackOverflow: function(allocSize) {
  1231. abort('Stack overflow! Attempted to allocate ' + allocSize + ' bytes on the stack, but stack has only ' + (STACK_MAX - stackSave() + allocSize) + ' bytes available!');
  1232. },
  1233. #if WASM_BACKEND == 0
  1234. $stackAlloc__asm: true,
  1235. $stackAlloc__sig: 'ii',
  1236. $stackAlloc__deps: ['$abortStackOverflow'],
  1237. $stackAlloc: function(size) {
  1238. size = size|0;
  1239. var ret = 0;
  1240. ret = STACKTOP;
  1241. STACKTOP = (STACKTOP + size)|0;
  1242. STACKTOP = (STACKTOP + 15)&-16;
  1243. #if ASSERTIONS || STACK_OVERFLOW_CHECK >= 2
  1244. if ((STACKTOP|0) >= (STACK_MAX|0)) abortStackOverflow(size|0);
  1245. #endif
  1246. return ret|0;
  1247. },
  1248. $stackSave__asm: true,
  1249. $stackSave__sig: 'i',
  1250. $stackSave: function() {
  1251. return STACKTOP|0;
  1252. },
  1253. $stackRestore__asm: true,
  1254. $stackRestore__sig: 'vi',
  1255. $stackRestore: function(top) {
  1256. top = top|0;
  1257. STACKTOP = top;
  1258. },
  1259. #endif
  1260. #endif
  1261. llvm_flt_rounds: function() {
  1262. return -1; // 'indeterminable' for FLT_ROUNDS
  1263. },
  1264. llvm_expect_i32__inline: function(val, expected) {
  1265. return '(' + val + ')';
  1266. },
  1267. llvm_objectsize_i32: function() { return -1 }, // TODO: support this
  1268. llvm_dbg_declare__inline: function() { throw 'llvm_debug_declare' }, // avoid warning
  1269. llvm_bitreverse_i32__asm: true,
  1270. llvm_bitreverse_i32__sig: 'ii',
  1271. llvm_bitreverse_i32: function(x) {
  1272. x = x|0;
  1273. x = ((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1);
  1274. x = ((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2);
  1275. x = ((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4);
  1276. x = ((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8);
  1277. return (x >>> 16) | (x << 16);
  1278. },
  1279. // llvm-nacl
  1280. llvm_nacl_atomic_store_i32__inline: true,
  1281. llvm_nacl_atomic_cmpxchg_i8__inline: true,
  1282. llvm_nacl_atomic_cmpxchg_i16__inline: true,
  1283. llvm_nacl_atomic_cmpxchg_i32__inline: true,
  1284. // ==========================================================================
  1285. // llvm-mono integration
  1286. // ==========================================================================
  1287. llvm_mono_load_i8_p0i8: function(ptr) {
  1288. return {{{ makeGetValue('ptr', 0, 'i8') }}};
  1289. },
  1290. llvm_mono_store_i8_p0i8: function(value, ptr) {
  1291. {{{ makeSetValue('ptr', 0, 'value', 'i8') }}};
  1292. },
  1293. llvm_mono_load_i16_p0i16: function(ptr) {
  1294. return {{{ makeGetValue('ptr', 0, 'i16') }}};
  1295. },
  1296. llvm_mono_store_i16_p0i16: function(value, ptr) {
  1297. {{{ makeSetValue('ptr', 0, 'value', 'i16') }}};
  1298. },
  1299. llvm_mono_load_i32_p0i32: function(ptr) {
  1300. return {{{ makeGetValue('ptr', 0, 'i32') }}};
  1301. },
  1302. llvm_mono_store_i32_p0i32: function(value, ptr) {
  1303. {{{ makeSetValue('ptr', 0, 'value', 'i32') }}};
  1304. },
  1305. // ==========================================================================
  1306. // math.h
  1307. // ==========================================================================
  1308. cos: 'Math_cos',
  1309. cosf: 'Math_cos',
  1310. cosl: 'Math_cos',
  1311. sin: 'Math_sin',
  1312. sinf: 'Math_sin',
  1313. sinl: 'Math_sin',
  1314. tan: 'Math_tan',
  1315. tanf: 'Math_tan',
  1316. tanl: 'Math_tan',
  1317. acos: 'Math_acos',
  1318. acosf: 'Math_acos',
  1319. acosl: 'Math_acos',
  1320. asin: 'Math_asin',
  1321. asinf: 'Math_asin',
  1322. asinl: 'Math_asin',
  1323. atan: 'Math_atan',
  1324. atanf: 'Math_atan',
  1325. atanl: 'Math_atan',
  1326. atan2: 'Math_atan2',
  1327. atan2f: 'Math_atan2',
  1328. atan2l: 'Math_atan2',
  1329. exp: 'Math_exp',
  1330. expf: 'Math_exp',
  1331. expl: 'Math_exp',
  1332. log: 'Math_log',
  1333. logf: 'Math_log',
  1334. logl: 'Math_log',
  1335. sqrt: 'Math_sqrt',
  1336. sqrtf: 'Math_sqrt',
  1337. sqrtl: 'Math_sqrt',
  1338. fabs: 'Math_abs',
  1339. fabsf: 'Math_abs',
  1340. fabsl: 'Math_abs',
  1341. llvm_fabs_f32: 'Math_abs',
  1342. llvm_fabs_f64: 'Math_abs',
  1343. ceil: 'Math_ceil',
  1344. ceilf: 'Math_ceil',
  1345. ceill: 'Math_ceil',
  1346. floor: 'Math_floor',
  1347. floorf: 'Math_floor',
  1348. floorl: 'Math_floor',
  1349. pow: 'Math_pow',
  1350. powf: 'Math_pow',
  1351. powl: 'Math_pow',
  1352. llvm_sqrt_f32: 'Math_sqrt',
  1353. llvm_sqrt_f64: 'Math_sqrt',
  1354. llvm_pow_f32: 'Math_pow',
  1355. llvm_pow_f64: 'Math_pow',
  1356. llvm_powi_f32: 'Math_pow',
  1357. llvm_powi_f64: 'Math_pow',
  1358. llvm_log_f32: 'Math_log',
  1359. llvm_log_f64: 'Math_log',
  1360. llvm_exp_f32: 'Math_exp',
  1361. llvm_exp_f64: 'Math_exp',
  1362. llvm_cos_f32: 'Math_cos',
  1363. llvm_cos_f64: 'Math_cos',
  1364. llvm_sin_f32: 'Math_sin',
  1365. llvm_sin_f64: 'Math_sin',
  1366. llvm_trunc_f32: 'Math_trunc',
  1367. llvm_trunc_f64: 'Math_trunc',
  1368. llvm_ceil_f32: 'Math_ceil',
  1369. llvm_ceil_f64: 'Math_ceil',
  1370. llvm_floor_f32: 'Math_floor',
  1371. llvm_floor_f64: 'Math_floor',
  1372. llvm_exp2_f32: function(x) {
  1373. return Math.pow(2, x);
  1374. },
  1375. llvm_exp2_f64__sig: 'dd',
  1376. llvm_exp2_f64: 'llvm_exp2_f32',
  1377. llvm_log2_f32: function(x) {
  1378. return Math.log(x) / Math.LN2; // TODO: Math.log2, when browser support is there
  1379. },
  1380. llvm_log2_f64__sig: 'dd',
  1381. llvm_log2_f64: 'llvm_log2_f32',
  1382. llvm_log10_f32: function(x) {
  1383. return Math.log(x) / Math.LN10; // TODO: Math.log10, when browser support is there
  1384. },
  1385. llvm_log10_f64__sig: 'dd',
  1386. llvm_log10_f64: 'llvm_log10_f32',
  1387. llvm_copysign_f32: function(x, y) {
  1388. return y < 0 || (y === 0 && 1/y < 0) ? -Math_abs(x) : Math_abs(x);
  1389. },
  1390. llvm_copysign_f64: function(x, y) {
  1391. return y < 0 || (y === 0 && 1/y < 0) ? -Math_abs(x) : Math_abs(x);
  1392. },
  1393. round__asm: true,
  1394. round__sig: 'dd',
  1395. round__deps: ['Math_floor', 'Math_ceil'],
  1396. round: function(d) {
  1397. d = +d;
  1398. return d >= +0 ? +Math_floor(d + +0.5) : +Math_ceil(d - +0.5);
  1399. },
  1400. roundf__asm: true,
  1401. roundf__sig: 'ff',
  1402. roundf__deps: ['Math_floor', 'Math_ceil'],
  1403. roundf: function(d) {
  1404. d = +d;
  1405. return d >= +0 ? +Math_floor(d + +0.5) : +Math_ceil(d - +0.5);
  1406. },
  1407. llvm_round_f64__asm: true,
  1408. llvm_round_f64__sig: 'dd',
  1409. llvm_round_f64__deps: ['Math_floor', 'Math_ceil'],
  1410. llvm_round_f64: function(d) {
  1411. d = +d;
  1412. return d >= +0 ? +Math_floor(d + +0.5) : +Math_ceil(d - +0.5);
  1413. },
  1414. llvm_round_f32__asm: true,
  1415. llvm_round_f32__sig: 'ff',
  1416. llvm_round_f32__deps: ['Math_floor', 'Math_ceil'],
  1417. llvm_round_f32: function(f) {
  1418. f = +f;
  1419. return f >= +0 ? +Math_floor(f + +0.5) : +Math_ceil(f - +0.5); // TODO: use fround?
  1420. },
  1421. rintf__asm: true,
  1422. rintf__sig: 'ff',
  1423. rintf__deps: ['round', 'Math_floor'],
  1424. rintf: function(f) {
  1425. f = +f;
  1426. return (f - +Math_floor(f) != .5) ? +_round(f) : +_round(f / +2) * +2;
  1427. },
  1428. // TODO: fround?
  1429. llvm_rint_f32__asm: true,
  1430. llvm_rint_f32__sig: 'ff',
  1431. llvm_rint_f32__deps: ['roundf', 'Math_floor'],
  1432. llvm_rint_f32: function(f) {
  1433. f = +f;
  1434. return (f - +Math_floor(f) != .5) ? +_roundf(f) : +_roundf(f / +2) * +2;
  1435. },
  1436. llvm_rint_f64__asm: true,
  1437. llvm_rint_f64__sig: 'dd',
  1438. llvm_rint_f64__deps: ['round', 'Math_floor'],
  1439. llvm_rint_f64: function(f) {
  1440. f = +f;
  1441. return (f - +Math_floor(f) != .5) ? +_round(f) : +_round(f / +2) * +2;
  1442. },
  1443. // TODO: fround?
  1444. llvm_nearbyint_f32__asm: true,
  1445. llvm_nearbyint_f32__sig: 'ff',
  1446. llvm_nearbyint_f32__deps: ['roundf', 'Math_floor'],
  1447. llvm_nearbyint_f32: function(f) {
  1448. f = +f;
  1449. return (f - +Math_floor(f) != .5) ? +_roundf(f) : +_roundf(f / +2) * +2;
  1450. },
  1451. llvm_nearbyint_f64__asm: true,
  1452. llvm_nearbyint_f64__sig: 'dd',
  1453. llvm_nearbyint_f64__deps: ['round', 'Math_floor'],
  1454. llvm_nearbyint_f64: function(f) {
  1455. f = +f;
  1456. return (f - +Math_floor(f) != .5) ? +_round(f) : +_round(f / +2) * +2;
  1457. },
  1458. // min/max num do not quite match the behavior of JS and wasm min/max:
  1459. // llvm and libc return the non-NaN if one is NaN, while JS and wasm
  1460. // return the NaN :(
  1461. // see also https://github.com/WebAssembly/design/issues/214
  1462. llvm_minnum_f32__asm: true,
  1463. llvm_minnum_f32__sig: 'ff',
  1464. llvm_minnum_f32__deps: ['Math_min'],
  1465. llvm_minnum_f32: function(x, y) {
  1466. x = +x;
  1467. y = +y;
  1468. if (x != x) return +y;
  1469. if (y != y) return +x;
  1470. return +Math_min(+x, +y);
  1471. },
  1472. llvm_minnum_f64__asm: true,
  1473. llvm_minnum_f64__sig: 'dd',
  1474. llvm_minnum_f64__deps: ['Math_min'],
  1475. llvm_minnum_f64: function(x, y) {
  1476. x = +x;
  1477. y = +y;
  1478. if (x != x) return +y;
  1479. if (y != y) return +x;
  1480. return +Math_min(+x, +y);
  1481. },
  1482. llvm_maxnum_f32__asm: true,
  1483. llvm_maxnum_f32__sig: 'ff',
  1484. llvm_maxnum_f32__deps: ['Math_max'],
  1485. llvm_maxnum_f32: function(x, y) {
  1486. x = +x;
  1487. y = +y;
  1488. if (x != x) return +y;
  1489. if (y != y) return +x;
  1490. return +Math_max(+x, +y);
  1491. },
  1492. llvm_maxnum_f64__asm: true,
  1493. llvm_maxnum_f64__sig: 'dd',
  1494. llvm_maxnum_f64__deps: ['Math_max'],
  1495. llvm_maxnum_f64: function(x, y) {
  1496. x = +x;
  1497. y = +y;
  1498. if (x != x) return +y;
  1499. if (y != y) return +x;
  1500. return +Math_max(+x, +y);
  1501. },
  1502. // ==========================================================================
  1503. // dlfcn.h - Dynamic library loading
  1504. //
  1505. // Some limitations:
  1506. //
  1507. // * Minification on each file separately may not work, as they will
  1508. // have different shortened names. You can in theory combine them, then
  1509. // minify, then split... perhaps.
  1510. //
  1511. // * LLVM optimizations may fail. If the child wants to access a function
  1512. // in the parent, LLVM opts may remove it from the parent when it is
  1513. // being compiled. Not sure how to tell LLVM to not do so.
  1514. // ==========================================================================
  1515. #if MAIN_MODULE == 0
  1516. dlopen: function(filename, flag) {
  1517. abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking");
  1518. },
  1519. dlclose: function(handle) {
  1520. abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking");
  1521. },
  1522. dlsym: function(handle, symbol) {
  1523. abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking");
  1524. },
  1525. dlerror: function() {
  1526. abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking");
  1527. },
  1528. dladdr: function(address, info) {
  1529. abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking");
  1530. },
  1531. #else // MAIN_MODULE != 0
  1532. $DLFCN: {
  1533. error: null,
  1534. errorMsg: null,
  1535. },
  1536. // void* dlopen(const char* filename, int flag);
  1537. dlopen__deps: ['$DLFCN', '$FS', '$ENV'],
  1538. dlopen__proxy: 'sync',
  1539. dlopen__sig: 'iii',
  1540. dlopen: function(filenameAddr, flag) {
  1541. // void *dlopen(const char *file, int mode);
  1542. // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlopen.html
  1543. var searchpaths = [];
  1544. var filename;
  1545. if (filenameAddr === 0) {
  1546. filename = '__self__';
  1547. } else {
  1548. filename = UTF8ToString(filenameAddr);
  1549. var isValidFile = function (filename) {
  1550. var target = FS.findObject(filename);
  1551. return target && !target.isFolder && !target.isDevice;
  1552. };
  1553. if (!isValidFile(filename)) {
  1554. if (ENV['LD_LIBRARY_PATH']) {
  1555. searchpaths = ENV['LD_LIBRARY_PATH'].split(':');
  1556. }
  1557. for (var ident in searchpaths) {
  1558. var searchfile = PATH.join2(searchpaths[ident], filename);
  1559. if (isValidFile(searchfile)) {
  1560. filename = searchfile;
  1561. break;
  1562. }
  1563. }
  1564. }
  1565. }
  1566. // We don't care about RTLD_NOW and RTLD_LAZY.
  1567. var flags = {
  1568. global: Boolean(flag & 256), // RTLD_GLOBAL
  1569. nodelete: Boolean(flag & 4096), // RTLD_NODELETE
  1570. fs: FS, // load libraries from provided filesystem
  1571. }
  1572. try {
  1573. var handle = loadDynamicLibrary(filename, flags)
  1574. } catch (e) {
  1575. #if ASSERTIONS
  1576. err('Error in loading dynamic library ' + filename + ": " + e);
  1577. #endif
  1578. DLFCN.errorMsg = 'Could not load dynamic lib: ' + filename + '\n' + e;
  1579. return 0;
  1580. }
  1581. return handle;
  1582. },
  1583. // int dlclose(void* handle);
  1584. dlclose__deps: ['$DLFCN'],
  1585. dlclose__proxy: 'sync',
  1586. dlclose__sig: 'ii',
  1587. dlclose: function(handle) {
  1588. // int dlclose(void *handle);
  1589. // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlclose.html
  1590. if (!LDSO.loadedLibs[handle]) {
  1591. DLFCN.errorMsg = 'Tried to dlclose() unopened handle: ' + handle;
  1592. return 1;
  1593. } else {
  1594. var lib_record = LDSO.loadedLibs[handle];
  1595. if (--lib_record.refcount == 0) {
  1596. if (lib_record.module.cleanups) {
  1597. lib_record.module.cleanups.forEach(function(cleanup) { cleanup() });
  1598. }
  1599. delete LDSO.loadedLibNames[lib_record.name];
  1600. delete LDSO.loadedLibs[handle];
  1601. }
  1602. return 0;
  1603. }
  1604. },
  1605. // void* dlsym(void* handle, const char* symbol);
  1606. dlsym__deps: ['$DLFCN'],
  1607. dlsym__proxy: 'sync',
  1608. dlsym__sig: 'iii',
  1609. dlsym: function(handle, symbol) {
  1610. // void *dlsym(void *restrict handle, const char *restrict name);
  1611. // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
  1612. symbol = UTF8ToString(symbol);
  1613. if (!LDSO.loadedLibs[handle]) {
  1614. DLFCN.errorMsg = 'Tried to dlsym() from an unopened handle: ' + handle;
  1615. return 0;
  1616. }
  1617. var lib = LDSO.loadedLibs[handle];
  1618. var isMainModule = lib.module == Module;
  1619. var mangled = '_' + symbol;
  1620. var modSymbol = mangled;
  1621. #if WASM_BACKEND
  1622. if (!isMainModule) {
  1623. modSymbol = symbol;
  1624. }
  1625. #endif
  1626. if (!lib.module.hasOwnProperty(modSymbol)) {
  1627. DLFCN.errorMsg = ('Tried to lookup unknown symbol "' + modSymbol +
  1628. '" in dynamic lib: ' + lib.name);
  1629. return 0;
  1630. }
  1631. var result = lib.module[modSymbol];
  1632. #if WASM
  1633. // Attempt to get the real "unwrapped" symbol so we have more chance of
  1634. // getting wasm function which can be added to a table.
  1635. if (isMainModule) {
  1636. #if WASM_BACKEND
  1637. var asmSymbol = symbol;
  1638. #else
  1639. var asmSymbol = mangled;
  1640. #endif
  1641. if (lib.module["asm"][asmSymbol]) {
  1642. result = lib.module["asm"][asmSymbol];
  1643. }
  1644. }
  1645. #endif
  1646. if (typeof result !== 'function')
  1647. return result;
  1648. #if WASM && EMULATE_FUNCTION_POINTER_CASTS
  1649. // for wasm with emulated function pointers, the i64 ABI is used for all
  1650. // function calls, so we can't just call addFunction on something JS
  1651. // can call (which does not use that ABI), as the function pointer would
  1652. // not be usable from wasm. instead, the wasm has exported function pointers
  1653. // for everything we need, with prefix fp$, use those
  1654. result = lib.module['fp$' + symbol];
  1655. if (typeof result === 'object') {
  1656. // a breaking change in the wasm spec, globals are now objects
  1657. // https://github.com/WebAssembly/mutable-global/issues/1
  1658. result = result.value;
  1659. }
  1660. #if ASSERTIONS
  1661. assert(typeof result === 'number', 'could not find function pointer for ' + symbol);
  1662. #endif // ASSERTIONS
  1663. return result;
  1664. #else // WASM && EMULATE_FUNCTION_POINTER_CASTS
  1665. #if WASM
  1666. // Insert the function into the wasm table. Since we know the function
  1667. // comes directly from the loaded wasm module we can insert it directly
  1668. // into the table, avoiding any JS interaction.
  1669. return addFunctionWasm(result);
  1670. #else
  1671. // convert the exported function into a function pointer using our generic
  1672. // JS mechanism.
  1673. return addFunction(result);
  1674. #endif // WASM
  1675. #endif // WASM && EMULATE_FUNCTION_POINTER_CASTS
  1676. },
  1677. // char* dlerror(void);
  1678. dlerror__deps: ['$DLFCN', '$stringToNewUTF8'],
  1679. dlerror__proxy: 'sync',
  1680. dlerror__sig: 'i',
  1681. dlerror: function() {
  1682. // char *dlerror(void);
  1683. // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlerror.html
  1684. if (DLFCN.errorMsg === null) {
  1685. return 0;
  1686. } else {
  1687. if (DLFCN.error) _free(DLFCN.error);
  1688. DLFCN.error = stringToNewUTF8(DLFCN.errorMsg);
  1689. DLFCN.errorMsg = null;
  1690. return DLFCN.error;
  1691. }
  1692. },
  1693. dladdr__deps: ['$stringToNewUTF8', '_getExecutableName'],
  1694. dladdr__proxy: 'sync',
  1695. dladdr__sig: 'iii',
  1696. dladdr: function(addr, info) {
  1697. // report all function pointers as coming from this program itself XXX not really correct in any way
  1698. var fname = stringToNewUTF8(__getExecutableName()); // XXX leak
  1699. {{{ makeSetValue('info', 0, 'fname', 'i32') }}};
  1700. {{{ makeSetValue('info', Runtime.QUANTUM_SIZE, '0', 'i32') }}};
  1701. {{{ makeSetValue('info', Runtime.QUANTUM_SIZE*2, '0', 'i32') }}};
  1702. {{{ makeSetValue('info', Runtime.QUANTUM_SIZE*3, '0', 'i32') }}};
  1703. return 1;
  1704. },
  1705. #endif // MAIN_MODULE != 0
  1706. // ==========================================================================
  1707. // pwd.h
  1708. // ==========================================================================
  1709. // TODO: Implement.
  1710. // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/pwd.h.html
  1711. getpwuid: function(uid) {
  1712. return 0; // NULL
  1713. },
  1714. // ==========================================================================
  1715. // time.h
  1716. // ==========================================================================
  1717. clock: function() {
  1718. if (_clock.start === undefined) _clock.start = Date.now();
  1719. return ((Date.now() - _clock.start) * ({{{ cDefine('CLOCKS_PER_SEC') }}} / 1000))|0;
  1720. },
  1721. time: function(ptr) {
  1722. var ret = (Date.now()/1000)|0;
  1723. if (ptr) {
  1724. {{{ makeSetValue('ptr', 0, 'ret', 'i32') }}};
  1725. }
  1726. return ret;
  1727. },
  1728. difftime: function(time1, time0) {
  1729. return time1 - time0;
  1730. },
  1731. // Statically allocated time struct.
  1732. __tm_current: '{{{ makeStaticAlloc(C_STRUCTS.tm.__size__) }}}',
  1733. // Statically allocated copy of the string "GMT" for gmtime() to point to
  1734. __tm_timezone: '{{{ makeStaticString("GMT") }}}',
  1735. // Statically allocated time strings.
  1736. __tm_formatted: '{{{ makeStaticAlloc(C_STRUCTS.tm.__size__) }}}',
  1737. mktime__deps: ['tzset'],
  1738. mktime__sig: 'ii',
  1739. mktime: function(tmPtr) {
  1740. _tzset();
  1741. var date = new Date({{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_year, 'i32') }}} + 1900,
  1742. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'i32') }}},
  1743. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'i32') }}},
  1744. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'i32') }}},
  1745. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_min, 'i32') }}},
  1746. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'i32') }}},
  1747. 0);
  1748. // There's an ambiguous hour when the time goes back; the tm_isdst field is
  1749. // used to disambiguate it. Date() basically guesses, so we fix it up if it
  1750. // guessed wrong, or fill in tm_isdst with the guess if it's -1.
  1751. var dst = {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_isdst, 'i32') }}};
  1752. var guessedOffset = date.getTimezoneOffset();
  1753. var start = new Date(date.getFullYear(), 0, 1);
  1754. var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
  1755. var winterOffset = start.getTimezoneOffset();
  1756. var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South
  1757. if (dst < 0) {
  1758. // Attention: some regions don't have DST at all.
  1759. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, 'Number(summerOffset != winterOffset && dstOffset == guessedOffset)', 'i32') }}};
  1760. } else if ((dst > 0) != (dstOffset == guessedOffset)) {
  1761. var nonDstOffset = Math.max(winterOffset, summerOffset);
  1762. var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
  1763. // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
  1764. date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000);
  1765. }
  1766. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getDay()', 'i32') }}};
  1767. var yday = ((date.getTime() - start.getTime()) / (1000 * 60 * 60 * 24))|0;
  1768. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}};
  1769. return (date.getTime() / 1000)|0;
  1770. },
  1771. timelocal: 'mktime',
  1772. gmtime__deps: ['__tm_current', 'gmtime_r'],
  1773. gmtime: function(time) {
  1774. return _gmtime_r(time, ___tm_current);
  1775. },
  1776. gmtime_r__deps: ['__tm_timezone'],
  1777. gmtime_r: function(time, tmPtr) {
  1778. var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000);
  1779. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getUTCSeconds()', 'i32') }}};
  1780. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getUTCMinutes()', 'i32') }}};
  1781. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getUTCHours()', 'i32') }}};
  1782. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'date.getUTCDate()', 'i32') }}};
  1783. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'date.getUTCMonth()', 'i32') }}};
  1784. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_year, 'date.getUTCFullYear()-1900', 'i32') }}};
  1785. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getUTCDay()', 'i32') }}};
  1786. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_gmtoff, '0', 'i32') }}};
  1787. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, '0', 'i32') }}};
  1788. var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
  1789. var yday = ((date.getTime() - start) / (1000 * 60 * 60 * 24))|0;
  1790. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}};
  1791. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_zone, '___tm_timezone', 'i32') }}};
  1792. return tmPtr;
  1793. },
  1794. timegm__deps: ['tzset'],
  1795. timegm: function(tmPtr) {
  1796. _tzset();
  1797. var time = Date.UTC({{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_year, 'i32') }}} + 1900,
  1798. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'i32') }}},
  1799. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'i32') }}},
  1800. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'i32') }}},
  1801. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_min, 'i32') }}},
  1802. {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'i32') }}},
  1803. 0);
  1804. var date = new Date(time);
  1805. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getUTCDay()', 'i32') }}};
  1806. var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
  1807. var yday = ((date.getTime() - start) / (1000 * 60 * 60 * 24))|0;
  1808. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}};
  1809. return (date.getTime() / 1000)|0;
  1810. },
  1811. localtime__deps: ['__tm_current', 'localtime_r'],
  1812. localtime: function(time) {
  1813. return _localtime_r(time, ___tm_current);
  1814. },
  1815. localtime_r__deps: ['__tm_timezone', 'tzset'],
  1816. localtime_r: function(time, tmPtr) {
  1817. _tzset();
  1818. var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000);
  1819. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getSeconds()', 'i32') }}};
  1820. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getMinutes()', 'i32') }}};
  1821. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getHours()', 'i32') }}};
  1822. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'date.getDate()', 'i32') }}};
  1823. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'date.getMonth()', 'i32') }}};
  1824. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_year, 'date.getFullYear()-1900', 'i32') }}};
  1825. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getDay()', 'i32') }}};
  1826. var start = new Date(date.getFullYear(), 0, 1);
  1827. var yday = ((date.getTime() - start.getTime()) / (1000 * 60 * 60 * 24))|0;
  1828. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}};
  1829. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_gmtoff, '-(date.getTimezoneOffset() * 60)', 'i32') }}};
  1830. // Attention: DST is in December in South, and some regions don't have DST at all.
  1831. var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
  1832. var winterOffset = start.getTimezoneOffset();
  1833. var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0;
  1834. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, 'dst', 'i32') }}};
  1835. var zonePtr = {{{ makeGetValue('__get_tzname()', 'dst ? ' + Runtime.QUANTUM_SIZE + ' : 0', 'i32') }}};
  1836. {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_zone, 'zonePtr', 'i32') }}};
  1837. return tmPtr;
  1838. },
  1839. asctime__deps: ['__tm_formatted', 'asctime_r'],
  1840. asctime: function(tmPtr) {
  1841. return _asctime_r(tmPtr, ___tm_formatted);
  1842. },
  1843. asctime_r__deps: ['__tm_formatted', 'mktime'],
  1844. asctime_r: function(tmPtr, buf) {
  1845. var date = {
  1846. tm_sec: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'i32') }}},
  1847. tm_min: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_min, 'i32') }}},
  1848. tm_hour: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'i32') }}},
  1849. tm_mday: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'i32') }}},
  1850. tm_mon: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'i32') }}},
  1851. tm_year: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_year, 'i32') }}},
  1852. tm_wday: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'i32') }}}
  1853. };
  1854. var days = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ];
  1855. var months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1856. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
  1857. var s = days[date.tm_wday] + ' ' + months[date.tm_mon] +
  1858. (date.tm_mday < 10 ? ' ' : ' ') + date.tm_mday +
  1859. (date.tm_hour < 10 ? ' 0' : ' ') + date.tm_hour +
  1860. (date.tm_min < 10 ? ':0' : ':') + date.tm_min +
  1861. (date.tm_sec < 10 ? ':0' : ':') + date.tm_sec +
  1862. ' ' + (1900 + date.tm_year) + "\n";
  1863. // asctime_r is specced to behave in an undefined manner if the algorithm would attempt
  1864. // to write out more than 26 bytes (including the null terminator).
  1865. // See http://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html
  1866. // Our undefined behavior is to truncate the write to at most 26 bytes, including null terminator.
  1867. stringToUTF8(s, buf, 26);
  1868. return buf;
  1869. },
  1870. ctime__deps: ['__tm_current', 'ctime_r'],
  1871. ctime: function(timer) {
  1872. return _ctime_r(timer, ___tm_current);
  1873. },
  1874. ctime_r__deps: ['localtime_r', 'asctime_r'
  1875. #if MINIMAL_RUNTIME && !WASM_BACKEND
  1876. , '$stackSave', '$stackAlloc', '$stackRestore'
  1877. #endif
  1878. ],
  1879. ctime_r: function(time, buf) {
  1880. var stack = stackSave();
  1881. var rv = _asctime_r(_localtime_r(time, stackAlloc({{{ C_STRUCTS.tm.__size__ }}})), buf);
  1882. stackRestore(stack);
  1883. return rv;
  1884. },
  1885. dysize: function(year) {
  1886. var leap = ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)));
  1887. return leap ? 366 : 365;
  1888. },
  1889. // TODO: Initialize these to defaults on startup from system settings.
  1890. // Note: glibc has one fewer underscore for all of these. Also used in other related functions (timegm)
  1891. tzset__proxy: 'sync',
  1892. tzset__sig: 'v',
  1893. #if MINIMAL_RUNTIME
  1894. tzset__deps: ['$allocateUTF8'],
  1895. #endif
  1896. tzset: function() {
  1897. // TODO: Use (malleable) environment variables instead of system settings.
  1898. if (_tzset.called) return;
  1899. _tzset.called = true;
  1900. // timezone is specified as seconds west of UTC ("The external variable
  1901. // `timezone` shall be set to the difference, in seconds, between
  1902. // Coordinated Universal Time (UTC) and local standard time."), the same
  1903. // as returned by getTimezoneOffset().
  1904. // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
  1905. {{{ makeSetValue('__get_timezone()', '0', '(new Date()).getTimezoneOffset() * 60', 'i32') }}};
  1906. var currentYear = new Date().getFullYear();
  1907. var winter = new Date(currentYear, 0, 1);
  1908. var summer = new Date(currentYear, 6, 1);
  1909. {{{ makeSetValue('__get_daylight()', '0', 'Number(winter.getTimezoneOffset() != summer.getTimezoneOffset())', 'i32') }}};
  1910. function extractZone(date) {
  1911. var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
  1912. return match ? match[1] : "GMT";
  1913. };
  1914. var winterName = extractZone(winter);
  1915. var summerName = extractZone(summer);
  1916. var winterNamePtr = allocateUTF8(winterName);
  1917. var summerNamePtr = allocateUTF8(summerName);
  1918. if (summer.getTimezoneOffset() < winter.getTimezoneOffset()) {
  1919. // Northern hemisphere
  1920. {{{ makeSetValue('__get_tzname()', '0', 'winterNamePtr', 'i32') }}};
  1921. {{{ makeSetValue('__get_tzname()', Runtime.QUANTUM_SIZE, 'summerNamePtr', 'i32') }}};
  1922. } else {
  1923. {{{ makeSetValue('__get_tzname()', '0', 'summerNamePtr', 'i32') }}};
  1924. {{{ makeSetValue('__get_tzname()', Runtime.QUANTUM_SIZE, 'winterNamePtr', 'i32') }}};
  1925. }
  1926. },
  1927. stime__deps: ['$setErrNo'],
  1928. stime: function(when) {
  1929. setErrNo({{{ cDefine('EPERM') }}});
  1930. return -1;
  1931. },
  1932. __map_file__deps: ['$setErrNo'],
  1933. __map_file: function(pathname, size) {
  1934. setErrNo({{{ cDefine('EPERM') }}});
  1935. return -1;
  1936. },
  1937. _MONTH_DAYS_REGULAR: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
  1938. _MONTH_DAYS_LEAP: [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
  1939. _isLeapYear: function(year) {
  1940. return year%4 === 0 && (year%100 !== 0 || year%400 === 0);
  1941. },
  1942. _arraySum: function(array, index) {
  1943. var sum = 0;
  1944. for (var i = 0; i <= index; sum += array[i++]) {
  1945. // no-op
  1946. }
  1947. return sum;
  1948. },
  1949. _addDays__deps: ['_isLeapYear', '_MONTH_DAYS_LEAP', '_MONTH_DAYS_REGULAR'],
  1950. _addDays: function(date, days) {
  1951. var newDate = new Date(date.getTime());
  1952. while(days > 0) {
  1953. var leap = __isLeapYear(newDate.getFullYear());
  1954. var currentMonth = newDate.getMonth();
  1955. var daysInCurrentMonth = (leap ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR)[currentMonth];
  1956. if (days > daysInCurrentMonth-newDate.getDate()) {
  1957. // we spill over to next month
  1958. days -= (daysInCurrentMonth-newDate.getDate()+1);
  1959. newDate.setDate(1);
  1960. if (currentMonth < 11) {
  1961. newDate.setMonth(currentMonth+1)
  1962. } else {
  1963. newDate.setMonth(0);
  1964. newDate.setFullYear(newDate.getFullYear()+1);
  1965. }
  1966. } else {
  1967. // we stay in current month
  1968. newDate.setDate(newDate.getDate()+days);
  1969. return newDate;
  1970. }
  1971. }
  1972. return newDate;
  1973. },
  1974. // Note: this is not used in STANDALONE_WASM mode, because it is more
  1975. // compact to do it in JS.
  1976. strftime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'
  1977. #if MINIMAL_RUNTIME
  1978. , '$intArrayFromString', '$writeArrayToMemory'
  1979. #endif
  1980. ],
  1981. strftime: function(s, maxsize, format, tm) {
  1982. // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr);
  1983. // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html
  1984. var tm_zone = {{{ makeGetValue('tm', C_STRUCTS.tm.tm_zone, 'i32') }}};
  1985. var date = {
  1986. tm_sec: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_sec, 'i32') }}},
  1987. tm_min: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_min, 'i32') }}},
  1988. tm_hour: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_hour, 'i32') }}},
  1989. tm_mday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_mday, 'i32') }}},
  1990. tm_mon: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_mon, 'i32') }}},
  1991. tm_year: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_year, 'i32') }}},
  1992. tm_wday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_wday, 'i32') }}},
  1993. tm_yday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_yday, 'i32') }}},
  1994. tm_isdst: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_isdst, 'i32') }}},
  1995. tm_gmtoff: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_gmtoff, 'i32') }}},
  1996. tm_zone: tm_zone ? UTF8ToString(tm_zone) : ''
  1997. };
  1998. var pattern = UTF8ToString(format);
  1999. // expand format
  2000. var EXPANSION_RULES_1 = {
  2001. '%c': '%a %b %d %H:%M:%S %Y', // Replaced by the locale's appropriate date and time representation - e.g., Mon Aug 3 14:02:01 2013
  2002. '%D': '%m/%d/%y', // Equivalent to %m / %d / %y
  2003. '%F': '%Y-%m-%d', // Equivalent to %Y - %m - %d
  2004. '%h': '%b', // Equivalent to %b
  2005. '%r': '%I:%M:%S %p', // Replaced by the time in a.m. and p.m. notation
  2006. '%R': '%H:%M', // Replaced by the time in 24-hour notation
  2007. '%T': '%H:%M:%S', // Replaced by the time
  2008. '%x': '%m/%d/%y', // Replaced by the locale's appropriate date representation
  2009. '%X': '%H:%M:%S', // Replaced by the locale's appropriate time representation
  2010. // Modified Conversion Specifiers
  2011. '%Ec': '%c', // Replaced by the locale's alternative appropriate date and time representation.
  2012. '%EC': '%C', // Replaced by the name of the base year (period) in the locale's alternative representation.
  2013. '%Ex': '%m/%d/%y', // Replaced by the locale's alternative date representation.
  2014. '%EX': '%H:%M:%S', // Replaced by the locale's alternative time representation.
  2015. '%Ey': '%y', // Replaced by the offset from %EC (year only) in the locale's alternative representation.
  2016. '%EY': '%Y', // Replaced by the full alternative year representation.
  2017. '%Od': '%d', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading zeros if there is any alternative symbol for zero; otherwise, with leading <space> characters.
  2018. '%Oe': '%e', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading <space> characters.
  2019. '%OH': '%H', // Replaced by the hour (24-hour clock) using the locale's alternative numeric symbols.
  2020. '%OI': '%I', // Replaced by the hour (12-hour clock) using the locale's alternative numeric symbols.
  2021. '%Om': '%m', // Replaced by the month using the locale's alternative numeric symbols.
  2022. '%OM': '%M', // Replaced by the minutes using the locale's alternative numeric symbols.
  2023. '%OS': '%S', // Replaced by the seconds using the locale's alternative numeric symbols.
  2024. '%Ou': '%u', // Replaced by the weekday as a number in the locale's alternative representation (Monday=1).
  2025. '%OU': '%U', // Replaced by the week number of the year (Sunday as the first day of the week, rules corresponding to %U ) using the locale's alternative numeric symbols.
  2026. '%OV': '%V', // Replaced by the week number of the year (Monday as the first day of the week, rules corresponding to %V ) using the locale's alternative numeric symbols.
  2027. '%Ow': '%w', // Replaced by the number of the weekday (Sunday=0) using the locale's alternative numeric symbols.
  2028. '%OW': '%W', // Replaced by the week number of the year (Monday as the first day of the week) using the locale's alternative numeric symbols.
  2029. '%Oy': '%y', // Replaced by the year (offset from %C ) using the locale's alternative numeric symbols.
  2030. };
  2031. for (var rule in EXPANSION_RULES_1) {
  2032. pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]);
  2033. }
  2034. var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  2035. var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
  2036. function leadingSomething(value, digits, character) {
  2037. var str = typeof value === 'number' ? value.toString() : (value || '');
  2038. while (str.length < digits) {
  2039. str = character[0]+str;
  2040. }
  2041. return str;
  2042. }
  2043. function leadingNulls(value, digits) {
  2044. return leadingSomething(value, digits, '0');
  2045. }
  2046. function compareByDay(date1, date2) {
  2047. function sgn(value) {
  2048. return value < 0 ? -1 : (value > 0 ? 1 : 0);
  2049. }
  2050. var compare;
  2051. if ((compare = sgn(date1.getFullYear()-date2.getFullYear())) === 0) {
  2052. if ((compare = sgn(date1.getMonth()-date2.getMonth())) === 0) {
  2053. compare = sgn(date1.getDate()-date2.getDate());
  2054. }
  2055. }
  2056. return compare;
  2057. }
  2058. function getFirstWeekStartDate(janFourth) {
  2059. switch (janFourth.getDay()) {
  2060. case 0: // Sunday
  2061. return new Date(janFourth.getFullYear()-1, 11, 29);
  2062. case 1: // Monday
  2063. return janFourth;
  2064. case 2: // Tuesday
  2065. return new Date(janFourth.getFullYear(), 0, 3);
  2066. case 3: // Wednesday
  2067. return new Date(janFourth.getFullYear(), 0, 2);
  2068. case 4: // Thursday
  2069. return new Date(janFourth.getFullYear(), 0, 1);
  2070. case 5: // Friday
  2071. return new Date(janFourth.getFullYear()-1, 11, 31);
  2072. case 6: // Saturday
  2073. return new Date(janFourth.getFullYear()-1, 11, 30);
  2074. }
  2075. }
  2076. function getWeekBasedYear(date) {
  2077. var thisDate = __addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday);
  2078. var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
  2079. var janFourthNextYear = new Date(thisDate.getFullYear()+1, 0, 4);
  2080. var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
  2081. var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
  2082. if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {
  2083. // this date is after the start of the first week of this year
  2084. if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {
  2085. return thisDate.getFullYear()+1;
  2086. } else {
  2087. return thisDate.getFullYear();
  2088. }
  2089. } else {
  2090. return thisDate.getFullYear()-1;
  2091. }
  2092. }
  2093. var EXPANSION_RULES_2 = {
  2094. '%a': function(date) {
  2095. return WEEKDAYS[date.tm_wday].substring(0,3);
  2096. },
  2097. '%A': function(date) {
  2098. return WEEKDAYS[date.tm_wday];
  2099. },
  2100. '%b': function(date) {
  2101. return MONTHS[date.tm_mon].substring(0,3);
  2102. },
  2103. '%B': function(date) {
  2104. return MONTHS[date.tm_mon];
  2105. },
  2106. '%C': function(date) {
  2107. var year = date.tm_year+1900;
  2108. return leadingNulls((year/100)|0,2);
  2109. },
  2110. '%d': function(date) {
  2111. return leadingNulls(date.tm_mday, 2);
  2112. },
  2113. '%e': function(date) {
  2114. return leadingSomething(date.tm_mday, 2, ' ');
  2115. },
  2116. '%g': function(date) {
  2117. // %g, %G, and %V give values according to the ISO 8601:2000 standard week-based year.
  2118. // In this system, weeks begin on a Monday and week 1 of the year is the week that includes
  2119. // January 4th, which is also the week that includes the first Thursday of the year, and
  2120. // is also the first week that contains at least four days in the year.
  2121. // If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of
  2122. // the last week of the preceding year; thus, for Saturday 2nd January 1999,
  2123. // %G is replaced by 1998 and %V is replaced by 53. If December 29th, 30th,
  2124. // or 31st is a Monday, it and any following days are part of week 1 of the following year.
  2125. // Thus, for Tuesday 30th December 1997, %G is replaced by 1998 and %V is replaced by 01.
  2126. return getWeekBasedYear(date).toString().substring(2);
  2127. },
  2128. '%G': function(date) {
  2129. return getWeekBasedYear(date);
  2130. },
  2131. '%H': function(date) {
  2132. return leadingNulls(date.tm_hour, 2);
  2133. },
  2134. '%I': function(date) {
  2135. var twelveHour = date.tm_hour;
  2136. if (twelveHour == 0) twelveHour = 12;
  2137. else if (twelveHour > 12) twelveHour -= 12;
  2138. return leadingNulls(twelveHour, 2);
  2139. },
  2140. '%j': function(date) {
  2141. // Day of the year (001-366)
  2142. return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, date.tm_mon-1), 3);
  2143. },
  2144. '%m': function(date) {
  2145. return leadingNulls(date.tm_mon+1, 2);
  2146. },
  2147. '%M': function(date) {
  2148. return leadingNulls(date.tm_min, 2);
  2149. },
  2150. '%n': function() {
  2151. return '\n';
  2152. },
  2153. '%p': function(date) {
  2154. if (date.tm_hour >= 0 && date.tm_hour < 12) {
  2155. return 'AM';
  2156. } else {
  2157. return 'PM';
  2158. }
  2159. },
  2160. '%S': function(date) {
  2161. return leadingNulls(date.tm_sec, 2);
  2162. },
  2163. '%t': function() {
  2164. return '\t';
  2165. },
  2166. '%u': function(date) {
  2167. return date.tm_wday || 7;
  2168. },
  2169. '%U': function(date) {
  2170. // Replaced by the week number of the year as a decimal number [00,53].
  2171. // The first Sunday of January is the first day of week 1;
  2172. // days in the new year before this are in week 0. [ tm_year, tm_wday, tm_yday]
  2173. var janFirst = new Date(date.tm_year+1900, 0, 1);
  2174. var firstSunday = janFirst.getDay() === 0 ? janFirst : __addDays(janFirst, 7-janFirst.getDay());
  2175. var endDate = new Date(date.tm_year+1900, date.tm_mon, date.tm_mday);
  2176. // is target date after the first Sunday?
  2177. if (compareByDay(firstSunday, endDate) < 0) {
  2178. // calculate difference in days between first Sunday and endDate
  2179. var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth()-1)-31;
  2180. var firstSundayUntilEndJanuary = 31-firstSunday.getDate();
  2181. var days = firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();
  2182. return leadingNulls(Math.ceil(days/7), 2);
  2183. }
  2184. return compareByDay(firstSunday, janFirst) === 0 ? '01': '00';
  2185. },
  2186. '%V': function(date) {
  2187. // Replaced by the week number of the year (Monday as the first day of the week)
  2188. // as a decimal number [01,53]. If the week containing 1 January has four
  2189. // or more days in the new year, then it is considered week 1.
  2190. // Otherwise, it is the last week of the previous year, and the next week is week 1.
  2191. // Both January 4th and the first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday]
  2192. var janFourthThisYear = new Date(date.tm_year+1900, 0, 4);
  2193. var janFourthNextYear = new Date(date.tm_year+1901, 0, 4);
  2194. var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
  2195. var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
  2196. var endDate = __addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday);
  2197. if (compareByDay(endDate, firstWeekStartThisYear) < 0) {
  2198. // if given date is before this years first week, then it belongs to the 53rd week of last year
  2199. return '53';
  2200. }
  2201. if (compareByDay(firstWeekStartNextYear, endDate) <= 0) {
  2202. // if given date is after next years first week, then it belongs to the 01th week of next year
  2203. return '01';
  2204. }
  2205. // given date is in between CW 01..53 of this calendar year
  2206. var daysDifference;
  2207. if (firstWeekStartThisYear.getFullYear() < date.tm_year+1900) {
  2208. // first CW of this year starts last year
  2209. daysDifference = date.tm_yday+32-firstWeekStartThisYear.getDate()
  2210. } else {
  2211. // first CW of this year starts this year
  2212. daysDifference = date.tm_yday+1-firstWeekStartThisYear.getDate();
  2213. }
  2214. return leadingNulls(Math.ceil(daysDifference/7), 2);
  2215. },
  2216. '%w': function(date) {
  2217. return date.tm_wday;
  2218. },
  2219. '%W': function(date) {
  2220. // Replaced by the week number of the year as a decimal number [00,53].
  2221. // The first Monday of January is the first day of week 1;
  2222. // days in the new year before this are in week 0. [ tm_year, tm_wday, tm_yday]
  2223. var janFirst = new Date(date.tm_year, 0, 1);
  2224. var firstMonday = janFirst.getDay() === 1 ? janFirst : __addDays(janFirst, janFirst.getDay() === 0 ? 1 : 7-janFirst.getDay()+1);
  2225. var endDate = new Date(date.tm_year+1900, date.tm_mon, date.tm_mday);
  2226. // is target date after the first Monday?
  2227. if (compareByDay(firstMonday, endDate) < 0) {
  2228. var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth()-1)-31;
  2229. var firstMondayUntilEndJanuary = 31-firstMonday.getDate();
  2230. var days = firstMondayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();
  2231. return leadingNulls(Math.ceil(days/7), 2);
  2232. }
  2233. return compareByDay(firstMonday, janFirst) === 0 ? '01': '00';
  2234. },
  2235. '%y': function(date) {
  2236. // Replaced by the last two digits of the year as a decimal number [00,99]. [ tm_year]
  2237. return (date.tm_year+1900).toString().substring(2);
  2238. },
  2239. '%Y': function(date) {
  2240. // Replaced by the year as a decimal number (for example, 1997). [ tm_year]
  2241. return date.tm_year+1900;
  2242. },
  2243. '%z': function(date) {
  2244. // Replaced by the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ).
  2245. // For example, "-0430" means 4 hours 30 minutes behind UTC (west of Greenwich).
  2246. var off = date.tm_gmtoff;
  2247. var ahead = off >= 0;
  2248. off = Math.abs(off) / 60;
  2249. // convert from minutes into hhmm format (which means 60 minutes = 100 units)
  2250. off = (off / 60)*100 + (off % 60);
  2251. return (ahead ? '+' : '-') + String("0000" + off).slice(-4);
  2252. },
  2253. '%Z': function(date) {
  2254. return date.tm_zone;
  2255. },
  2256. '%%': function() {
  2257. return '%';
  2258. }
  2259. };
  2260. for (var rule in EXPANSION_RULES_2) {
  2261. if (pattern.indexOf(rule) >= 0) {
  2262. pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date));
  2263. }
  2264. }
  2265. var bytes = intArrayFromString(pattern, false);
  2266. if (bytes.length > maxsize) {
  2267. return 0;
  2268. }
  2269. writeArrayToMemory(bytes, s);
  2270. return bytes.length-1;
  2271. },
  2272. strftime_l__deps: ['strftime'],
  2273. strftime_l: function(s, maxsize, format, tm) {
  2274. return _strftime(s, maxsize, format, tm); // no locale support yet
  2275. },
  2276. strptime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP', '$jstoi_q'
  2277. #if MINIMAL_RUNTIME
  2278. , '$intArrayFromString'
  2279. #endif
  2280. ],
  2281. strptime: function(buf, format, tm) {
  2282. // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm);
  2283. // http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html
  2284. var pattern = UTF8ToString(format);
  2285. // escape special characters
  2286. // TODO: not sure we really need to escape all of these in JS regexps
  2287. var SPECIAL_CHARS = '\\!@#$^&*()+=-[]/{}|:<>?,.';
  2288. for (var i=0, ii=SPECIAL_CHARS.length; i<ii; ++i) {
  2289. pattern = pattern.replace(new RegExp('\\'+SPECIAL_CHARS[i], 'g'), '\\'+SPECIAL_CHARS[i]);
  2290. }
  2291. // reduce number of matchers
  2292. var EQUIVALENT_MATCHERS = {
  2293. '%A': '%a',
  2294. '%B': '%b',
  2295. '%c': '%a %b %d %H:%M:%S %Y',
  2296. '%D': '%m\\/%d\\/%y',
  2297. '%e': '%d',
  2298. '%F': '%Y-%m-%d',
  2299. '%h': '%b',
  2300. '%R': '%H\\:%M',
  2301. '%r': '%I\\:%M\\:%S\\s%p',
  2302. '%T': '%H\\:%M\\:%S',
  2303. '%x': '%m\\/%d\\/(?:%y|%Y)',
  2304. '%X': '%H\\:%M\\:%S'
  2305. };
  2306. for (var matcher in EQUIVALENT_MATCHERS) {
  2307. pattern = pattern.replace(matcher, EQUIVALENT_MATCHERS[matcher]);
  2308. }
  2309. // TODO: take care of locale
  2310. var DATE_PATTERNS = {
  2311. /* weeday name */ '%a': '(?:Sun(?:day)?)|(?:Mon(?:day)?)|(?:Tue(?:sday)?)|(?:Wed(?:nesday)?)|(?:Thu(?:rsday)?)|(?:Fri(?:day)?)|(?:Sat(?:urday)?)',
  2312. /* month name */ '%b': '(?:Jan(?:uary)?)|(?:Feb(?:ruary)?)|(?:Mar(?:ch)?)|(?:Apr(?:il)?)|May|(?:Jun(?:e)?)|(?:Jul(?:y)?)|(?:Aug(?:ust)?)|(?:Sep(?:tember)?)|(?:Oct(?:ober)?)|(?:Nov(?:ember)?)|(?:Dec(?:ember)?)',
  2313. /* century */ '%C': '\\d\\d',
  2314. /* day of month */ '%d': '0[1-9]|[1-9](?!\\d)|1\\d|2\\d|30|31',
  2315. /* hour (24hr) */ '%H': '\\d(?!\\d)|[0,1]\\d|20|21|22|23',
  2316. /* hour (12hr) */ '%I': '\\d(?!\\d)|0\\d|10|11|12',
  2317. /* day of year */ '%j': '00[1-9]|0?[1-9](?!\\d)|0?[1-9]\\d(?!\\d)|[1,2]\\d\\d|3[0-6]\\d',
  2318. /* month */ '%m': '0[1-9]|[1-9](?!\\d)|10|11|12',
  2319. /* minutes */ '%M': '0\\d|\\d(?!\\d)|[1-5]\\d',
  2320. /* whitespace */ '%n': '\\s',
  2321. /* AM/PM */ '%p': 'AM|am|PM|pm|A\\.M\\.|a\\.m\\.|P\\.M\\.|p\\.m\\.',
  2322. /* seconds */ '%S': '0\\d|\\d(?!\\d)|[1-5]\\d|60',
  2323. /* week number */ '%U': '0\\d|\\d(?!\\d)|[1-4]\\d|50|51|52|53',
  2324. /* week number */ '%W': '0\\d|\\d(?!\\d)|[1-4]\\d|50|51|52|53',
  2325. /* weekday number */ '%w': '[0-6]',
  2326. /* 2-digit year */ '%y': '\\d\\d',
  2327. /* 4-digit year */ '%Y': '\\d\\d\\d\\d',
  2328. /* % */ '%%': '%',
  2329. /* whitespace */ '%t': '\\s',
  2330. };
  2331. var MONTH_NUMBERS = {JAN: 0, FEB: 1, MAR: 2, APR: 3, MAY: 4, JUN: 5, JUL: 6, AUG: 7, SEP: 8, OCT: 9, NOV: 10, DEC: 11};
  2332. var DAY_NUMBERS_SUN_FIRST = {SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6};
  2333. var DAY_NUMBERS_MON_FIRST = {MON: 0, TUE: 1, WED: 2, THU: 3, FRI: 4, SAT: 5, SUN: 6};
  2334. for (var datePattern in DATE_PATTERNS) {
  2335. pattern = pattern.replace(datePattern, '('+datePattern+DATE_PATTERNS[datePattern]+')');
  2336. }
  2337. // take care of capturing groups
  2338. var capture = [];
  2339. for (var i=pattern.indexOf('%'); i>=0; i=pattern.indexOf('%')) {
  2340. capture.push(pattern[i+1]);
  2341. pattern = pattern.replace(new RegExp('\\%'+pattern[i+1], 'g'), '');
  2342. }
  2343. var matches = new RegExp('^'+pattern, "i").exec(UTF8ToString(buf))
  2344. // out(UTF8ToString(buf)+ ' is matched by '+((new RegExp('^'+pattern)).source)+' into: '+JSON.stringify(matches));
  2345. function initDate() {
  2346. function fixup(value, min, max) {
  2347. return (typeof value !== 'number' || isNaN(value)) ? min : (value>=min ? (value<=max ? value: max): min);
  2348. };
  2349. return {
  2350. year: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_year, 'i32', 0, 0, 1) }}} + 1900 , 1970, 9999),
  2351. month: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_mon, 'i32', 0, 0, 1) }}}, 0, 11),
  2352. day: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_mday, 'i32', 0, 0, 1) }}}, 1, 31),
  2353. hour: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_hour, 'i32', 0, 0, 1) }}}, 0, 23),
  2354. min: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_min, 'i32', 0, 0, 1) }}}, 0, 59),
  2355. sec: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_sec, 'i32', 0, 0, 1) }}}, 0, 59)
  2356. };
  2357. };
  2358. if (matches) {
  2359. var date = initDate();
  2360. var value;
  2361. var getMatch = function(symbol) {
  2362. var pos = capture.indexOf(symbol);
  2363. // check if symbol appears in regexp
  2364. if (pos >= 0) {
  2365. // return matched value or null (falsy!) for non-matches
  2366. return matches[pos+1];
  2367. }
  2368. return;
  2369. };
  2370. // seconds
  2371. if ((value=getMatch('S'))) {
  2372. date.sec = jstoi_q(value);
  2373. }
  2374. // minutes
  2375. if ((value=getMatch('M'))) {
  2376. date.min = jstoi_q(value);
  2377. }
  2378. // hours
  2379. if ((value=getMatch('H'))) {
  2380. // 24h clock
  2381. date.hour = jstoi_q(value);
  2382. } else if ((value = getMatch('I'))) {
  2383. // AM/PM clock
  2384. var hour = jstoi_q(value);
  2385. if ((value=getMatch('p'))) {
  2386. hour += value.toUpperCase()[0] === 'P' ? 12 : 0;
  2387. }
  2388. date.hour = hour;
  2389. }
  2390. // year
  2391. if ((value=getMatch('Y'))) {
  2392. // parse from four-digit year
  2393. date.year = jstoi_q(value);
  2394. } else if ((value=getMatch('y'))) {
  2395. // parse from two-digit year...
  2396. var year = jstoi_q(value);
  2397. if ((value=getMatch('C'))) {
  2398. // ...and century
  2399. year += jstoi_q(value)*100;
  2400. } else {
  2401. // ...and rule-of-thumb
  2402. year += year<69 ? 2000 : 1900;
  2403. }
  2404. date.year = year;
  2405. }
  2406. // month
  2407. if ((value=getMatch('m'))) {
  2408. // parse from month number
  2409. date.month = jstoi_q(value)-1;
  2410. } else if ((value=getMatch('b'))) {
  2411. // parse from month name
  2412. date.month = MONTH_NUMBERS[value.substring(0,3).toUpperCase()] || 0;
  2413. // TODO: derive month from day in year+year, week number+day of week+year
  2414. }
  2415. // day
  2416. if ((value=getMatch('d'))) {
  2417. // get day of month directly
  2418. date.day = jstoi_q(value);
  2419. } else if ((value=getMatch('j'))) {
  2420. // get day of month from day of year ...
  2421. var day = jstoi_q(value);
  2422. var leapYear = __isLeapYear(date.year);
  2423. for (var month=0; month<12; ++month) {
  2424. var daysUntilMonth = __arraySum(leapYear ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, month-1);
  2425. if (day<=daysUntilMonth+(leapYear ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR)[month]) {
  2426. date.day = day-daysUntilMonth;
  2427. }
  2428. }
  2429. } else if ((value=getMatch('a'))) {
  2430. // get day of month from weekday ...
  2431. var weekDay = value.substring(0,3).toUpperCase();
  2432. if ((value=getMatch('U'))) {
  2433. // ... and week number (Sunday being first day of week)
  2434. // Week number of the year (Sunday as the first day of the week) as a decimal number [00,53].
  2435. // All days in a new year preceding the first Sunday are considered to be in week 0.
  2436. var weekDayNumber = DAY_NUMBERS_SUN_FIRST[weekDay];
  2437. var weekNumber = jstoi_q(value);
  2438. // January 1st
  2439. var janFirst = new Date(date.year, 0, 1);
  2440. var endDate;
  2441. if (janFirst.getDay() === 0) {
  2442. // Jan 1st is a Sunday, and, hence in the 1st CW
  2443. endDate = __addDays(janFirst, weekDayNumber+7*(weekNumber-1));
  2444. } else {
  2445. // Jan 1st is not a Sunday, and, hence still in the 0th CW
  2446. endDate = __addDays(janFirst, 7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1));
  2447. }
  2448. date.day = endDate.getDate();
  2449. date.month = endDate.getMonth();
  2450. } else if ((value=getMatch('W'))) {
  2451. // ... and week number (Monday being first day of week)
  2452. // Week number of the year (Monday as the first day of the week) as a decimal number [00,53].
  2453. // All days in a new year preceding the first Monday are considered to be in week 0.
  2454. var weekDayNumber = DAY_NUMBERS_MON_FIRST[weekDay];
  2455. var weekNumber = jstoi_q(value);
  2456. // January 1st
  2457. var janFirst = new Date(date.year, 0, 1);
  2458. var endDate;
  2459. if (janFirst.getDay()===1) {
  2460. // Jan 1st is a Monday, and, hence in the 1st CW
  2461. endDate = __addDays(janFirst, weekDayNumber+7*(weekNumber-1));
  2462. } else {
  2463. // Jan 1st is not a Monday, and, hence still in the 0th CW
  2464. endDate = __addDays(janFirst, 7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1));
  2465. }
  2466. date.day = endDate.getDate();
  2467. date.month = endDate.getMonth();
  2468. }
  2469. }
  2470. /*
  2471. tm_sec int seconds after the minute 0-61*
  2472. tm_min int minutes after the hour 0-59
  2473. tm_hour int hours since midnight 0-23
  2474. tm_mday int day of the month 1-31
  2475. tm_mon int months since January 0-11
  2476. tm_year int years since 1900
  2477. tm_wday int days since Sunday 0-6
  2478. tm_yday int days since January 1 0-365
  2479. tm_isdst int Daylight Saving Time flag
  2480. */
  2481. var fullDate = new Date(date.year, date.month, date.day, date.hour, date.min, date.sec, 0);
  2482. {{{ makeSetValue('tm', C_STRUCTS.tm.tm_sec, 'fullDate.getSeconds()', 'i32') }}};
  2483. {{{ makeSetValue('tm', C_STRUCTS.tm.tm_min, 'fullDate.getMinutes()', 'i32') }}};
  2484. {{{ makeSetValue('tm', C_STRUCTS.tm.tm_hour, 'fullDate.getHours()', 'i32') }}};
  2485. {{{ makeSetValue('tm', C_STRUCTS.tm.tm_mday, 'fullDate.getDate()', 'i32') }}};
  2486. {{{ makeSetValue('tm', C_STRUCTS.tm.tm_mon, 'fullDate.getMonth()', 'i32') }}};
  2487. {{{ makeSetValue('tm', C_STRUCTS.tm.tm_year, 'fullDate.getFullYear()-1900', 'i32') }}};
  2488. {{{ makeSetValue('tm', C_STRUCTS.tm.tm_wday, 'fullDate.getDay()', 'i32') }}};
  2489. {{{ makeSetValue('tm', C_STRUCTS.tm.tm_yday, '__arraySum(__isLeapYear(fullDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, fullDate.getMonth()-1)+fullDate.getDate()-1', 'i32') }}};
  2490. {{{ makeSetValue('tm', C_STRUCTS.tm.tm_isdst, '0', 'i32') }}};
  2491. // we need to convert the matched sequence into an integer array to take care of UTF-8 characters > 0x7F
  2492. // TODO: not sure that intArrayFromString handles all unicode characters correctly
  2493. return buf+intArrayFromString(matches[0]).length-1;
  2494. }
  2495. return 0;
  2496. },
  2497. strptime_l__deps: ['strptime'],
  2498. strptime_l: function(buf, format, tm) {
  2499. return _strptime(buf, format, tm); // no locale support yet
  2500. },
  2501. getdate: function(string) {
  2502. // struct tm *getdate(const char *string);
  2503. // http://pubs.opengroup.org/onlinepubs/009695399/functions/getdate.html
  2504. // TODO: Implement.
  2505. return 0;
  2506. },
  2507. timespec_get__deps: ['clock_gettime', '$setErrNo'],
  2508. timespec_get: function(ts, base) {
  2509. //int timespec_get(struct timespec *ts, int base);
  2510. if (base !== {{{ cDefine('TIME_UTC') }}}) {
  2511. // There is no other implemented value than TIME_UTC; all other values are considered erroneous.
  2512. setErrNo({{{ cDefine('EINVAL') }}});
  2513. return 0;
  2514. }
  2515. var ret = _clock_gettime({{{ cDefine('CLOCK_REALTIME') }}}, ts);
  2516. return ret < 0 ? 0 : base;
  2517. },
  2518. // ==========================================================================
  2519. // sys/time.h
  2520. // ==========================================================================
  2521. clock_gettime__deps: ['emscripten_get_now', 'emscripten_get_now_is_monotonic', '$setErrNo'],
  2522. clock_gettime: function(clk_id, tp) {
  2523. // int clock_gettime(clockid_t clk_id, struct timespec *tp);
  2524. var now;
  2525. if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
  2526. now = Date.now();
  2527. } else if ((clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} || clk_id === {{{ cDefine('CLOCK_MONOTONIC_RAW') }}}) && _emscripten_get_now_is_monotonic) {
  2528. now = _emscripten_get_now();
  2529. } else {
  2530. setErrNo({{{ cDefine('EINVAL') }}});
  2531. return -1;
  2532. }
  2533. {{{ makeSetValue('tp', C_STRUCTS.timespec.tv_sec, '(now/1000)|0', 'i32') }}}; // seconds
  2534. {{{ makeSetValue('tp', C_STRUCTS.timespec.tv_nsec, '((now % 1000)*1000*1000)|0', 'i32') }}}; // nanoseconds
  2535. return 0;
  2536. },
  2537. __clock_gettime__sig: 'iii',
  2538. __clock_gettime: 'clock_gettime', // musl internal alias
  2539. clock_getres__deps: ['emscripten_get_now_res', 'emscripten_get_now_is_monotonic', '$setErrNo'],
  2540. clock_getres: function(clk_id, res) {
  2541. // int clock_getres(clockid_t clk_id, struct timespec *res);
  2542. var nsec;
  2543. if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) {
  2544. nsec = 1000 * 1000; // educated guess that it's milliseconds
  2545. } else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_is_monotonic) {
  2546. nsec = _emscripten_get_now_res();
  2547. } else {
  2548. setErrNo({{{ cDefine('EINVAL') }}});
  2549. return -1;
  2550. }
  2551. {{{ makeSetValue('res', C_STRUCTS.timespec.tv_sec, '(nsec/1000000000)|0', 'i32') }}};
  2552. {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, 'nsec', 'i32') }}} // resolution is nanoseconds
  2553. return 0;
  2554. },
  2555. clock_getcpuclockid: function(pid, clk_id) {
  2556. if (pid < 0) return {{{ cDefine('ESRCH') }}};
  2557. if (pid !== 0 && pid !== {{{ PROCINFO.pid }}}) return {{{ cDefine('ENOSYS') }}};
  2558. if (clk_id) {{{ makeSetValue('clk_id', 0, 2/*CLOCK_PROCESS_CPUTIME_ID*/, 'i32') }}};
  2559. return 0;
  2560. },
  2561. // http://pubs.opengroup.org/onlinepubs/000095399/basedefs/sys/time.h.html
  2562. gettimeofday: function(ptr) {
  2563. var now = Date.now();
  2564. {{{ makeSetValue('ptr', C_STRUCTS.timeval.tv_sec, '(now/1000)|0', 'i32') }}}; // seconds
  2565. {{{ makeSetValue('ptr', C_STRUCTS.timeval.tv_usec, '((now % 1000)*1000)|0', 'i32') }}}; // microseconds
  2566. return 0;
  2567. },
  2568. // ==========================================================================
  2569. // sys/timeb.h
  2570. // ==========================================================================
  2571. ftime: function(p) {
  2572. var millis = Date.now();
  2573. {{{ makeSetValue('p', C_STRUCTS.timeb.time, '(millis/1000)|0', 'i32') }}};
  2574. {{{ makeSetValue('p', C_STRUCTS.timeb.millitm, 'millis % 1000', 'i16') }}};
  2575. {{{ makeSetValue('p', C_STRUCTS.timeb.timezone, '0', 'i16') }}}; // Obsolete field
  2576. {{{ makeSetValue('p', C_STRUCTS.timeb.dstflag, '0', 'i16') }}}; // Obsolete field
  2577. return 0;
  2578. },
  2579. // ==========================================================================
  2580. // sys/times.h
  2581. // ==========================================================================
  2582. #if !WASM_BACKEND
  2583. times__deps: ['memset'],
  2584. #endif
  2585. times: function(buffer) {
  2586. // clock_t times(struct tms *buffer);
  2587. // http://pubs.opengroup.org/onlinepubs/009695399/functions/times.html
  2588. // NOTE: This is fake, since we can't calculate real CPU time usage in JS.
  2589. if (buffer !== 0) {
  2590. _memset(buffer, 0, {{{ C_STRUCTS.tms.__size__ }}});
  2591. }
  2592. return 0;
  2593. },
  2594. // ==========================================================================
  2595. // sys/types.h
  2596. // ==========================================================================
  2597. // http://www.kernel.org/doc/man-pages/online/pages/man3/minor.3.html
  2598. makedev__sig: 'iii',
  2599. makedev: function(maj, min) {
  2600. return ((maj) << 8 | (min));
  2601. },
  2602. gnu_dev_makedev: 'makedev',
  2603. major__sig: 'ii',
  2604. major: function(dev) {
  2605. return ((dev) >> 8);
  2606. },
  2607. gnu_dev_major: 'major',
  2608. minor__sig: 'ii',
  2609. minor: function(dev) {
  2610. return ((dev) & 0xff);
  2611. },
  2612. gnu_dev_minor: 'minor',
  2613. // ==========================================================================
  2614. // setjmp.h
  2615. // ==========================================================================
  2616. #if SUPPORT_LONGJMP
  2617. // asm.js-style setjmp/longjmp support for wasm binaryen backend.
  2618. // In asm.js compilation, various variables including setjmpId will be
  2619. // generated within 'var asm' in emscripten.py, while in wasm compilation,
  2620. // wasm side is considered as 'asm' so they are not generated. But
  2621. // saveSetjmp() needs setjmpId and no other functions in wasm side needs it.
  2622. // So we declare it here if WASM_BACKEND=1.
  2623. #if WASM_BACKEND == 1
  2624. $setjmpId: 0,
  2625. #endif
  2626. saveSetjmp__asm: true,
  2627. saveSetjmp__sig: 'iii',
  2628. #if WASM_BACKEND == 1
  2629. saveSetjmp__deps: ['realloc', '$setjmpId'],
  2630. #else
  2631. saveSetjmp__deps: ['realloc'],
  2632. #endif
  2633. saveSetjmp: function(env, label, table, size) {
  2634. // Not particularly fast: slow table lookup of setjmpId to label. But setjmp
  2635. // prevents relooping anyhow, so slowness is to be expected. And typical case
  2636. // is 1 setjmp per invocation, or less.
  2637. env = env|0;
  2638. label = label|0;
  2639. table = table|0;
  2640. size = size|0;
  2641. var i = 0;
  2642. setjmpId = (setjmpId+1)|0;
  2643. {{{ makeSetValueAsm('env', '0', 'setjmpId', 'i32') }}};
  2644. while ((i|0) < (size|0)) {
  2645. if ({{{ makeGetValueAsm('table', '(i<<3)', 'i32') }}} == 0) {
  2646. {{{ makeSetValueAsm('table', '(i<<3)', 'setjmpId', 'i32') }}};
  2647. {{{ makeSetValueAsm('table', '(i<<3)+4', 'label', 'i32') }}};
  2648. // prepare next slot
  2649. {{{ makeSetValueAsm('table', '(i<<3)+8', '0', 'i32') }}};
  2650. {{{ makeSetTempRet0('size') }}};
  2651. return table | 0;
  2652. }
  2653. i = i+1|0;
  2654. }
  2655. // grow the table
  2656. size = (size*2)|0;
  2657. table = _realloc(table|0, 8*(size+1|0)|0) | 0;
  2658. table = _saveSetjmp(env|0, label|0, table|0, size|0) | 0;
  2659. {{{ makeSetTempRet0('size') }}};
  2660. return table | 0;
  2661. },
  2662. testSetjmp__asm: true,
  2663. testSetjmp__sig: 'iii',
  2664. testSetjmp: function(id, table, size) {
  2665. id = id|0;
  2666. table = table|0;
  2667. size = size|0;
  2668. var i = 0, curr = 0;
  2669. while ((i|0) < (size|0)) {
  2670. curr = {{{ makeGetValueAsm('table', '(i<<3)', 'i32') }}};
  2671. if ((curr|0) == 0) break;
  2672. if ((curr|0) == (id|0)) {
  2673. return {{{ makeGetValueAsm('table', '(i<<3)+4', 'i32') }}};
  2674. }
  2675. i = i+1|0;
  2676. }
  2677. return 0;
  2678. },
  2679. setjmp__deps: ['saveSetjmp', 'testSetjmp'],
  2680. setjmp__inline: function(env) {
  2681. // Save the label
  2682. return '_saveSetjmp(' + env + ', label, setjmpTable)|0';
  2683. },
  2684. longjmp__deps: ['saveSetjmp', 'testSetjmp'
  2685. #if WASM_BACKEND == 0
  2686. , 'setThrew'
  2687. #endif
  2688. ],
  2689. longjmp: function(env, value) {
  2690. _setThrew(env, value || 1);
  2691. throw 'longjmp';
  2692. },
  2693. emscripten_longjmp__deps: ['longjmp'],
  2694. emscripten_longjmp: function(env, value) {
  2695. _longjmp(env, value);
  2696. },
  2697. #endif
  2698. // ==========================================================================
  2699. // sys/wait.h
  2700. // ==========================================================================
  2701. wait__deps: ['$setErrNo'],
  2702. wait__sig: 'ii',
  2703. wait: function(stat_loc) {
  2704. // pid_t wait(int *stat_loc);
  2705. // http://pubs.opengroup.org/onlinepubs/009695399/functions/wait.html
  2706. // Makes no sense in a single-process environment.
  2707. setErrNo({{{ cDefine('ECHILD') }}});
  2708. return -1;
  2709. },
  2710. // NOTE: These aren't really the same, but we use the same stub for them all.
  2711. waitid: 'wait',
  2712. waitpid: 'wait',
  2713. wait3: 'wait',
  2714. wait4: 'wait',
  2715. // ==========================================================================
  2716. // errno.h
  2717. // ==========================================================================
  2718. $ERRNO_CODES: {
  2719. EPERM: {{{ cDefine('EPERM') }}},
  2720. ENOENT: {{{ cDefine('ENOENT') }}},
  2721. ESRCH: {{{ cDefine('ESRCH') }}},
  2722. EINTR: {{{ cDefine('EINTR') }}},
  2723. EIO: {{{ cDefine('EIO') }}},
  2724. ENXIO: {{{ cDefine('ENXIO') }}},
  2725. E2BIG: {{{ cDefine('E2BIG') }}},
  2726. ENOEXEC: {{{ cDefine('ENOEXEC') }}},
  2727. EBADF: {{{ cDefine('EBADF') }}},
  2728. ECHILD: {{{ cDefine('ECHILD') }}},
  2729. EAGAIN: {{{ cDefine('EAGAIN') }}},
  2730. EWOULDBLOCK: {{{ cDefine('EWOULDBLOCK') }}},
  2731. ENOMEM: {{{ cDefine('ENOMEM') }}},
  2732. EACCES: {{{ cDefine('EACCES') }}},
  2733. EFAULT: {{{ cDefine('EFAULT') }}},
  2734. ENOTBLK: {{{ cDefine('ENOTBLK') }}},
  2735. EBUSY: {{{ cDefine('EBUSY') }}},
  2736. EEXIST: {{{ cDefine('EEXIST') }}},
  2737. EXDEV: {{{ cDefine('EXDEV') }}},
  2738. ENODEV: {{{ cDefine('ENODEV') }}},
  2739. ENOTDIR: {{{ cDefine('ENOTDIR') }}},
  2740. EISDIR: {{{ cDefine('EISDIR') }}},
  2741. EINVAL: {{{ cDefine('EINVAL') }}},
  2742. ENFILE: {{{ cDefine('ENFILE') }}},
  2743. EMFILE: {{{ cDefine('EMFILE') }}},
  2744. ENOTTY: {{{ cDefine('ENOTTY') }}},
  2745. ETXTBSY: {{{ cDefine('ETXTBSY') }}},
  2746. EFBIG: {{{ cDefine('EFBIG') }}},
  2747. ENOSPC: {{{ cDefine('ENOSPC') }}},
  2748. ESPIPE: {{{ cDefine('ESPIPE') }}},
  2749. EROFS: {{{ cDefine('EROFS') }}},
  2750. EMLINK: {{{ cDefine('EMLINK') }}},
  2751. EPIPE: {{{ cDefine('EPIPE') }}},
  2752. EDOM: {{{ cDefine('EDOM') }}},
  2753. ERANGE: {{{ cDefine('ERANGE') }}},
  2754. ENOMSG: {{{ cDefine('ENOMSG') }}},
  2755. EIDRM: {{{ cDefine('EIDRM') }}},
  2756. ECHRNG: {{{ cDefine('ECHRNG') }}},
  2757. EL2NSYNC: {{{ cDefine('EL2NSYNC') }}},
  2758. EL3HLT: {{{ cDefine('EL3HLT') }}},
  2759. EL3RST: {{{ cDefine('EL3RST') }}},
  2760. ELNRNG: {{{ cDefine('ELNRNG') }}},
  2761. EUNATCH: {{{ cDefine('EUNATCH') }}},
  2762. ENOCSI: {{{ cDefine('ENOCSI') }}},
  2763. EL2HLT: {{{ cDefine('EL2HLT') }}},
  2764. EDEADLK: {{{ cDefine('EDEADLK') }}},
  2765. ENOLCK: {{{ cDefine('ENOLCK') }}},
  2766. EBADE: {{{ cDefine('EBADE') }}},
  2767. EBADR: {{{ cDefine('EBADR') }}},
  2768. EXFULL: {{{ cDefine('EXFULL') }}},
  2769. ENOANO: {{{ cDefine('ENOANO') }}},
  2770. EBADRQC: {{{ cDefine('EBADRQC') }}},
  2771. EBADSLT: {{{ cDefine('EBADSLT') }}},
  2772. EDEADLOCK: {{{ cDefine('EDEADLOCK') }}},
  2773. EBFONT: {{{ cDefine('EBFONT') }}},
  2774. ENOSTR: {{{ cDefine('ENOSTR') }}},
  2775. ENODATA: {{{ cDefine('ENODATA') }}},
  2776. ETIME: {{{ cDefine('ETIME') }}},
  2777. ENOSR: {{{ cDefine('ENOSR') }}},
  2778. ENONET: {{{ cDefine('ENONET') }}},
  2779. ENOPKG: {{{ cDefine('ENOPKG') }}},
  2780. EREMOTE: {{{ cDefine('EREMOTE') }}},
  2781. ENOLINK: {{{ cDefine('ENOLINK') }}},
  2782. EADV: {{{ cDefine('EADV') }}},
  2783. ESRMNT: {{{ cDefine('ESRMNT') }}},
  2784. ECOMM: {{{ cDefine('ECOMM') }}},
  2785. EPROTO: {{{ cDefine('EPROTO') }}},
  2786. EMULTIHOP: {{{ cDefine('EMULTIHOP') }}},
  2787. EDOTDOT: {{{ cDefine('EDOTDOT') }}},
  2788. EBADMSG: {{{ cDefine('EBADMSG') }}},
  2789. ENOTUNIQ: {{{ cDefine('ENOTUNIQ') }}},
  2790. EBADFD: {{{ cDefine('EBADFD') }}},
  2791. EREMCHG: {{{ cDefine('EREMCHG') }}},
  2792. ELIBACC: {{{ cDefine('ELIBACC') }}},
  2793. ELIBBAD: {{{ cDefine('ELIBBAD') }}},
  2794. ELIBSCN: {{{ cDefine('ELIBSCN') }}},
  2795. ELIBMAX: {{{ cDefine('ELIBMAX') }}},
  2796. ELIBEXEC: {{{ cDefine('ELIBEXEC') }}},
  2797. ENOSYS: {{{ cDefine('ENOSYS') }}},
  2798. ENOTEMPTY: {{{ cDefine('ENOTEMPTY') }}},
  2799. ENAMETOOLONG: {{{ cDefine('ENAMETOOLONG') }}},
  2800. ELOOP: {{{ cDefine('ELOOP') }}},
  2801. EOPNOTSUPP: {{{ cDefine('EOPNOTSUPP') }}},
  2802. EPFNOSUPPORT: {{{ cDefine('EPFNOSUPPORT') }}},
  2803. ECONNRESET: {{{ cDefine('ECONNRESET') }}},
  2804. ENOBUFS: {{{ cDefine('ENOBUFS') }}},
  2805. EAFNOSUPPORT: {{{ cDefine('EAFNOSUPPORT') }}},
  2806. EPROTOTYPE: {{{ cDefine('EPROTOTYPE') }}},
  2807. ENOTSOCK: {{{ cDefine('ENOTSOCK') }}},
  2808. ENOPROTOOPT: {{{ cDefine('ENOPROTOOPT') }}},
  2809. ESHUTDOWN: {{{ cDefine('ESHUTDOWN') }}},
  2810. ECONNREFUSED: {{{ cDefine('ECONNREFUSED') }}},
  2811. EADDRINUSE: {{{ cDefine('EADDRINUSE') }}},
  2812. ECONNABORTED: {{{ cDefine('ECONNABORTED') }}},
  2813. ENETUNREACH: {{{ cDefine('ENETUNREACH') }}},
  2814. ENETDOWN: {{{ cDefine('ENETDOWN') }}},
  2815. ETIMEDOUT: {{{ cDefine('ETIMEDOUT') }}},
  2816. EHOSTDOWN: {{{ cDefine('EHOSTDOWN') }}},
  2817. EHOSTUNREACH: {{{ cDefine('EHOSTUNREACH') }}},
  2818. EINPROGRESS: {{{ cDefine('EINPROGRESS') }}},
  2819. EALREADY: {{{ cDefine('EALREADY') }}},
  2820. EDESTADDRREQ: {{{ cDefine('EDESTADDRREQ') }}},
  2821. EMSGSIZE: {{{ cDefine('EMSGSIZE') }}},
  2822. EPROTONOSUPPORT: {{{ cDefine('EPROTONOSUPPORT') }}},
  2823. ESOCKTNOSUPPORT: {{{ cDefine('ESOCKTNOSUPPORT') }}},
  2824. EADDRNOTAVAIL: {{{ cDefine('EADDRNOTAVAIL') }}},
  2825. ENETRESET: {{{ cDefine('ENETRESET') }}},
  2826. EISCONN: {{{ cDefine('EISCONN') }}},
  2827. ENOTCONN: {{{ cDefine('ENOTCONN') }}},
  2828. ETOOMANYREFS: {{{ cDefine('ETOOMANYREFS') }}},
  2829. EUSERS: {{{ cDefine('EUSERS') }}},
  2830. EDQUOT: {{{ cDefine('EDQUOT') }}},
  2831. ESTALE: {{{ cDefine('ESTALE') }}},
  2832. ENOTSUP: {{{ cDefine('ENOTSUP') }}},
  2833. ENOMEDIUM: {{{ cDefine('ENOMEDIUM') }}},
  2834. EILSEQ: {{{ cDefine('EILSEQ') }}},
  2835. EOVERFLOW: {{{ cDefine('EOVERFLOW') }}},
  2836. ECANCELED: {{{ cDefine('ECANCELED') }}},
  2837. ENOTRECOVERABLE: {{{ cDefine('ENOTRECOVERABLE') }}},
  2838. EOWNERDEAD: {{{ cDefine('EOWNERDEAD') }}},
  2839. ESTRPIPE: {{{ cDefine('ESTRPIPE') }}},
  2840. },
  2841. $ERRNO_MESSAGES: {
  2842. 0: 'Success',
  2843. {{{ cDefine('EPERM') }}}: 'Not super-user',
  2844. {{{ cDefine('ENOENT') }}}: 'No such file or directory',
  2845. {{{ cDefine('ESRCH') }}}: 'No such process',
  2846. {{{ cDefine('EINTR') }}}: 'Interrupted system call',
  2847. {{{ cDefine('EIO') }}}: 'I/O error',
  2848. {{{ cDefine('ENXIO') }}}: 'No such device or address',
  2849. {{{ cDefine('E2BIG') }}}: 'Arg list too long',
  2850. {{{ cDefine('ENOEXEC') }}}: 'Exec format error',
  2851. {{{ cDefine('EBADF') }}}: 'Bad file number',
  2852. {{{ cDefine('ECHILD') }}}: 'No children',
  2853. {{{ cDefine('EWOULDBLOCK') }}}: 'No more processes',
  2854. {{{ cDefine('ENOMEM') }}}: 'Not enough core',
  2855. {{{ cDefine('EACCES') }}}: 'Permission denied',
  2856. {{{ cDefine('EFAULT') }}}: 'Bad address',
  2857. {{{ cDefine('ENOTBLK') }}}: 'Block device required',
  2858. {{{ cDefine('EBUSY') }}}: 'Mount device busy',
  2859. {{{ cDefine('EEXIST') }}}: 'File exists',
  2860. {{{ cDefine('EXDEV') }}}: 'Cross-device link',
  2861. {{{ cDefine('ENODEV') }}}: 'No such device',
  2862. {{{ cDefine('ENOTDIR') }}}: 'Not a directory',
  2863. {{{ cDefine('EISDIR') }}}: 'Is a directory',
  2864. {{{ cDefine('EINVAL') }}}: 'Invalid argument',
  2865. {{{ cDefine('ENFILE') }}}: 'Too many open files in system',
  2866. {{{ cDefine('EMFILE') }}}: 'Too many open files',
  2867. {{{ cDefine('ENOTTY') }}}: 'Not a typewriter',
  2868. {{{ cDefine('ETXTBSY') }}}: 'Text file busy',
  2869. {{{ cDefine('EFBIG') }}}: 'File too large',
  2870. {{{ cDefine('ENOSPC') }}}: 'No space left on device',
  2871. {{{ cDefine('ESPIPE') }}}: 'Illegal seek',
  2872. {{{ cDefine('EROFS') }}}: 'Read only file system',
  2873. {{{ cDefine('EMLINK') }}}: 'Too many links',
  2874. {{{ cDefine('EPIPE') }}}: 'Broken pipe',
  2875. {{{ cDefine('EDOM') }}}: 'Math arg out of domain of func',
  2876. {{{ cDefine('ERANGE') }}}: 'Math result not representable',
  2877. {{{ cDefine('ENOMSG') }}}: 'No message of desired type',
  2878. {{{ cDefine('EIDRM') }}}: 'Identifier removed',
  2879. {{{ cDefine('ECHRNG') }}}: 'Channel number out of range',
  2880. {{{ cDefine('EL2NSYNC') }}}: 'Level 2 not synchronized',
  2881. {{{ cDefine('EL3HLT') }}}: 'Level 3 halted',
  2882. {{{ cDefine('EL3RST') }}}: 'Level 3 reset',
  2883. {{{ cDefine('ELNRNG') }}}: 'Link number out of range',
  2884. {{{ cDefine('EUNATCH') }}}: 'Protocol driver not attached',
  2885. {{{ cDefine('ENOCSI') }}}: 'No CSI structure available',
  2886. {{{ cDefine('EL2HLT') }}}: 'Level 2 halted',
  2887. {{{ cDefine('EDEADLK') }}}: 'Deadlock condition',
  2888. {{{ cDefine('ENOLCK') }}}: 'No record locks available',
  2889. {{{ cDefine('EBADE') }}}: 'Invalid exchange',
  2890. {{{ cDefine('EBADR') }}}: 'Invalid request descriptor',
  2891. {{{ cDefine('EXFULL') }}}: 'Exchange full',
  2892. {{{ cDefine('ENOANO') }}}: 'No anode',
  2893. {{{ cDefine('EBADRQC') }}}: 'Invalid request code',
  2894. {{{ cDefine('EBADSLT') }}}: 'Invalid slot',
  2895. {{{ cDefine('EDEADLOCK') }}}: 'File locking deadlock error',
  2896. {{{ cDefine('EBFONT') }}}: 'Bad font file fmt',
  2897. {{{ cDefine('ENOSTR') }}}: 'Device not a stream',
  2898. {{{ cDefine('ENODATA') }}}: 'No data (for no delay io)',
  2899. {{{ cDefine('ETIME') }}}: 'Timer expired',
  2900. {{{ cDefine('ENOSR') }}}: 'Out of streams resources',
  2901. {{{ cDefine('ENONET') }}}: 'Machine is not on the network',
  2902. {{{ cDefine('ENOPKG') }}}: 'Package not installed',
  2903. {{{ cDefine('EREMOTE') }}}: 'The object is remote',
  2904. {{{ cDefine('ENOLINK') }}}: 'The link has been severed',
  2905. {{{ cDefine('EADV') }}}: 'Advertise error',
  2906. {{{ cDefine('ESRMNT') }}}: 'Srmount error',
  2907. {{{ cDefine('ECOMM') }}}: 'Communication error on send',
  2908. {{{ cDefine('EPROTO') }}}: 'Protocol error',
  2909. {{{ cDefine('EMULTIHOP') }}}: 'Multihop attempted',
  2910. {{{ cDefine('EDOTDOT') }}}: 'Cross mount point (not really error)',
  2911. {{{ cDefine('EBADMSG') }}}: 'Trying to read unreadable message',
  2912. {{{ cDefine('ENOTUNIQ') }}}: 'Given log. name not unique',
  2913. {{{ cDefine('EBADFD') }}}: 'f.d. invalid for this operation',
  2914. {{{ cDefine('EREMCHG') }}}: 'Remote address changed',
  2915. {{{ cDefine('ELIBACC') }}}: 'Can access a needed shared lib',
  2916. {{{ cDefine('ELIBBAD') }}}: 'Accessing a corrupted shared lib',
  2917. {{{ cDefine('ELIBSCN') }}}: '.lib section in a.out corrupted',
  2918. {{{ cDefine('ELIBMAX') }}}: 'Attempting to link in too many libs',
  2919. {{{ cDefine('ELIBEXEC') }}}: 'Attempting to exec a shared library',
  2920. {{{ cDefine('ENOSYS') }}}: 'Function not implemented',
  2921. {{{ cDefine('ENOTEMPTY') }}}: 'Directory not empty',
  2922. {{{ cDefine('ENAMETOOLONG') }}}: 'File or path name too long',
  2923. {{{ cDefine('ELOOP') }}}: 'Too many symbolic links',
  2924. {{{ cDefine('EOPNOTSUPP') }}}: 'Operation not supported on transport endpoint',
  2925. {{{ cDefine('EPFNOSUPPORT') }}}: 'Protocol family not supported',
  2926. {{{ cDefine('ECONNRESET') }}}: 'Connection reset by peer',
  2927. {{{ cDefine('ENOBUFS') }}}: 'No buffer space available',
  2928. {{{ cDefine('EAFNOSUPPORT') }}}: 'Address family not supported by protocol family',
  2929. {{{ cDefine('EPROTOTYPE') }}}: 'Protocol wrong type for socket',
  2930. {{{ cDefine('ENOTSOCK') }}}: 'Socket operation on non-socket',
  2931. {{{ cDefine('ENOPROTOOPT') }}}: 'Protocol not available',
  2932. {{{ cDefine('ESHUTDOWN') }}}: 'Can\'t send after socket shutdown',
  2933. {{{ cDefine('ECONNREFUSED') }}}: 'Connection refused',
  2934. {{{ cDefine('EADDRINUSE') }}}: 'Address already in use',
  2935. {{{ cDefine('ECONNABORTED') }}}: 'Connection aborted',
  2936. {{{ cDefine('ENETUNREACH') }}}: 'Network is unreachable',
  2937. {{{ cDefine('ENETDOWN') }}}: 'Network interface is not configured',
  2938. {{{ cDefine('ETIMEDOUT') }}}: 'Connection timed out',
  2939. {{{ cDefine('EHOSTDOWN') }}}: 'Host is down',
  2940. {{{ cDefine('EHOSTUNREACH') }}}: 'Host is unreachable',
  2941. {{{ cDefine('EINPROGRESS') }}}: 'Connection already in progress',
  2942. {{{ cDefine('EALREADY') }}}: 'Socket already connected',
  2943. {{{ cDefine('EDESTADDRREQ') }}}: 'Destination address required',
  2944. {{{ cDefine('EMSGSIZE') }}}: 'Message too long',
  2945. {{{ cDefine('EPROTONOSUPPORT') }}}: 'Unknown protocol',
  2946. {{{ cDefine('ESOCKTNOSUPPORT') }}}: 'Socket type not supported',
  2947. {{{ cDefine('EADDRNOTAVAIL') }}}: 'Address not available',
  2948. {{{ cDefine('ENETRESET') }}}: 'Connection reset by network',
  2949. {{{ cDefine('EISCONN') }}}: 'Socket is already connected',
  2950. {{{ cDefine('ENOTCONN') }}}: 'Socket is not connected',
  2951. {{{ cDefine('ETOOMANYREFS') }}}: 'Too many references',
  2952. {{{ cDefine('EUSERS') }}}: 'Too many users',
  2953. {{{ cDefine('EDQUOT') }}}: 'Quota exceeded',
  2954. {{{ cDefine('ESTALE') }}}: 'Stale file handle',
  2955. {{{ cDefine('ENOTSUP') }}}: 'Not supported',
  2956. {{{ cDefine('ENOMEDIUM') }}}: 'No medium (in tape drive)',
  2957. {{{ cDefine('EILSEQ') }}}: 'Illegal byte sequence',
  2958. {{{ cDefine('EOVERFLOW') }}}: 'Value too large for defined data type',
  2959. {{{ cDefine('ECANCELED') }}}: 'Operation canceled',
  2960. {{{ cDefine('ENOTRECOVERABLE') }}}: 'State not recoverable',
  2961. {{{ cDefine('EOWNERDEAD') }}}: 'Previous owner died',
  2962. {{{ cDefine('ESTRPIPE') }}}: 'Streams pipe error',
  2963. },
  2964. #if SUPPORT_ERRNO
  2965. $setErrNo__deps: ['__errno_location'],
  2966. $setErrNo: function(value) {
  2967. {{{makeSetValue("___errno_location()", 0, 'value', 'i32') }}};
  2968. return value;
  2969. },
  2970. #else
  2971. $setErrNo: function(value) {
  2972. #if ASSERTIONS
  2973. err('failed to set errno from JS');
  2974. #endif
  2975. return 0;
  2976. },
  2977. #endif
  2978. #if !WASM_BACKEND
  2979. // ==========================================================================
  2980. // sched.h (stubs only - no thread support yet!)
  2981. // ==========================================================================
  2982. sched_yield: function() {
  2983. return 0;
  2984. },
  2985. #endif
  2986. // ==========================================================================
  2987. // arpa/inet.h
  2988. // ==========================================================================
  2989. #if PROXY_POSIX_SOCKETS == 0
  2990. // old ipv4 only functions
  2991. inet_addr__deps: ['_inet_pton4_raw'],
  2992. inet_addr: function(ptr) {
  2993. var addr = __inet_pton4_raw(UTF8ToString(ptr));
  2994. if (addr === null) {
  2995. return -1;
  2996. }
  2997. return addr;
  2998. },
  2999. // ==========================================================================
  3000. // netinet/in.h
  3001. // ==========================================================================
  3002. in6addr_any:
  3003. '{{{ makeStaticAlloc(16) }}}',
  3004. in6addr_loopback:
  3005. '{{{ makeStaticAlloc(16) }}}',
  3006. // ==========================================================================
  3007. // netdb.h
  3008. // ==========================================================================
  3009. _inet_pton4_raw: function(str) {
  3010. var b = str.split('.');
  3011. for (var i = 0; i < 4; i++) {
  3012. var tmp = Number(b[i]);
  3013. if (isNaN(tmp)) return null;
  3014. b[i] = tmp;
  3015. }
  3016. return (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0;
  3017. },
  3018. _inet_ntop4_raw: function(addr) {
  3019. return (addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff)
  3020. },
  3021. _inet_pton6_raw__deps: ['htons', 'ntohs', '$jstoi_q'],
  3022. _inet_pton6_raw: function(str) {
  3023. var words;
  3024. var w, offset, z, i;
  3025. /* http://home.deds.nl/~aeron/regex/ */
  3026. var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i
  3027. var parts = [];
  3028. if (!valid6regx.test(str)) {
  3029. return null;
  3030. }
  3031. if (str === "::") {
  3032. return [0, 0, 0, 0, 0, 0, 0, 0];
  3033. }
  3034. // Z placeholder to keep track of zeros when splitting the string on ":"
  3035. if (str.indexOf("::") === 0) {
  3036. str = str.replace("::", "Z:"); // leading zeros case
  3037. } else {
  3038. str = str.replace("::", ":Z:");
  3039. }
  3040. if (str.indexOf(".") > 0) {
  3041. // parse IPv4 embedded stress
  3042. str = str.replace(new RegExp('[.]', 'g'), ":");
  3043. words = str.split(":");
  3044. words[words.length-4] = jstoi_q(words[words.length-4]) + jstoi_q(words[words.length-3])*256;
  3045. words[words.length-3] = jstoi_q(words[words.length-2]) + jstoi_q(words[words.length-1])*256;
  3046. words = words.slice(0, words.length-2);
  3047. } else {
  3048. words = str.split(":");
  3049. }
  3050. offset = 0; z = 0;
  3051. for (w=0; w < words.length; w++) {
  3052. if (typeof words[w] === 'string') {
  3053. if (words[w] === 'Z') {
  3054. // compressed zeros - write appropriate number of zero words
  3055. for (z = 0; z < (8 - words.length+1); z++) {
  3056. parts[w+z] = 0;
  3057. }
  3058. offset = z-1;
  3059. } else {
  3060. // parse hex to field to 16-bit value and write it in network byte-order
  3061. parts[w+offset] = _htons(parseInt(words[w],16));
  3062. }
  3063. } else {
  3064. // parsed IPv4 words
  3065. parts[w+offset] = words[w];
  3066. }
  3067. }
  3068. return [
  3069. (parts[1] << 16) | parts[0],
  3070. (parts[3] << 16) | parts[2],
  3071. (parts[5] << 16) | parts[4],
  3072. (parts[7] << 16) | parts[6]
  3073. ];
  3074. },
  3075. _inet_pton6__deps: ['_inet_pton6_raw'],
  3076. _inet_pton6: function(src, dst) {
  3077. var ints = __inet_pton6_raw(UTF8ToString(src));
  3078. if (ints === null) {
  3079. return 0;
  3080. }
  3081. for (var i = 0; i < 4; i++) {
  3082. {{{ makeSetValue('dst', 'i*4', 'ints[i]', 'i32') }}};
  3083. }
  3084. return 1;
  3085. },
  3086. _inet_ntop6_raw__deps: ['_inet_ntop4_raw'],
  3087. _inet_ntop6_raw: function(ints) {
  3088. // ref: http://www.ietf.org/rfc/rfc2373.txt - section 2.5.4
  3089. // Format for IPv4 compatible and mapped 128-bit IPv6 Addresses
  3090. // 128-bits are split into eight 16-bit words
  3091. // stored in network byte order (big-endian)
  3092. // | 80 bits | 16 | 32 bits |
  3093. // +-----------------------------------------------------------------+
  3094. // | 10 bytes | 2 | 4 bytes |
  3095. // +--------------------------------------+--------------------------+
  3096. // + 5 words | 1 | 2 words |
  3097. // +--------------------------------------+--------------------------+
  3098. // |0000..............................0000|0000| IPv4 ADDRESS | (compatible)
  3099. // +--------------------------------------+----+---------------------+
  3100. // |0000..............................0000|FFFF| IPv4 ADDRESS | (mapped)
  3101. // +--------------------------------------+----+---------------------+
  3102. var str = "";
  3103. var word = 0;
  3104. var longest = 0;
  3105. var lastzero = 0;
  3106. var zstart = 0;
  3107. var len = 0;
  3108. var i = 0;
  3109. var parts = [
  3110. ints[0] & 0xffff,
  3111. (ints[0] >> 16),
  3112. ints[1] & 0xffff,
  3113. (ints[1] >> 16),
  3114. ints[2] & 0xffff,
  3115. (ints[2] >> 16),
  3116. ints[3] & 0xffff,
  3117. (ints[3] >> 16)
  3118. ];
  3119. // Handle IPv4-compatible, IPv4-mapped, loopback and any/unspecified addresses
  3120. var hasipv4 = true;
  3121. var v4part = "";
  3122. // check if the 10 high-order bytes are all zeros (first 5 words)
  3123. for (i = 0; i < 5; i++) {
  3124. if (parts[i] !== 0) { hasipv4 = false; break; }
  3125. }
  3126. if (hasipv4) {
  3127. // low-order 32-bits store an IPv4 address (bytes 13 to 16) (last 2 words)
  3128. v4part = __inet_ntop4_raw(parts[6] | (parts[7] << 16));
  3129. // IPv4-mapped IPv6 address if 16-bit value (bytes 11 and 12) == 0xFFFF (6th word)
  3130. if (parts[5] === -1) {
  3131. str = "::ffff:";
  3132. str += v4part;
  3133. return str;
  3134. }
  3135. // IPv4-compatible IPv6 address if 16-bit value (bytes 11 and 12) == 0x0000 (6th word)
  3136. if (parts[5] === 0) {
  3137. str = "::";
  3138. //special case IPv6 addresses
  3139. if(v4part === "0.0.0.0") v4part = ""; // any/unspecified address
  3140. if(v4part === "0.0.0.1") v4part = "1";// loopback address
  3141. str += v4part;
  3142. return str;
  3143. }
  3144. }
  3145. // Handle all other IPv6 addresses
  3146. // first run to find the longest contiguous zero words
  3147. for (word = 0; word < 8; word++) {
  3148. if (parts[word] === 0) {
  3149. if (word - lastzero > 1) {
  3150. len = 0;
  3151. }
  3152. lastzero = word;
  3153. len++;
  3154. }
  3155. if (len > longest) {
  3156. longest = len;
  3157. zstart = word - longest + 1;
  3158. }
  3159. }
  3160. for (word = 0; word < 8; word++) {
  3161. if (longest > 1) {
  3162. // compress contiguous zeros - to produce "::"
  3163. if (parts[word] === 0 && word >= zstart && word < (zstart + longest) ) {
  3164. if (word === zstart) {
  3165. str += ":";
  3166. if (zstart === 0) str += ":"; //leading zeros case
  3167. }
  3168. continue;
  3169. }
  3170. }
  3171. // converts 16-bit words from big-endian to little-endian before converting to hex string
  3172. str += Number(_ntohs(parts[word] & 0xffff)).toString(16);
  3173. str += word < 7 ? ":" : "";
  3174. }
  3175. return str;
  3176. },
  3177. _read_sockaddr__deps: ['$Sockets', '_inet_ntop4_raw', '_inet_ntop6_raw', 'ntohs'],
  3178. _read_sockaddr: function (sa, salen) {
  3179. // family / port offsets are common to both sockaddr_in and sockaddr_in6
  3180. var family = {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in.sin_family, 'i16') }}};
  3181. var port = _ntohs({{{ makeGetValue('sa', C_STRUCTS.sockaddr_in.sin_port, 'i16', undefined, true) }}});
  3182. var addr;
  3183. switch (family) {
  3184. case {{{ cDefine('AF_INET') }}}:
  3185. if (salen !== {{{ C_STRUCTS.sockaddr_in.__size__ }}}) {
  3186. return { errno: {{{ cDefine('EINVAL') }}} };
  3187. }
  3188. addr = {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in.sin_addr.s_addr, 'i32') }}};
  3189. addr = __inet_ntop4_raw(addr);
  3190. break;
  3191. case {{{ cDefine('AF_INET6') }}}:
  3192. if (salen !== {{{ C_STRUCTS.sockaddr_in6.__size__ }}}) {
  3193. return { errno: {{{ cDefine('EINVAL') }}} };
  3194. }
  3195. addr = [
  3196. {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+0, 'i32') }}},
  3197. {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+4, 'i32') }}},
  3198. {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+8, 'i32') }}},
  3199. {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+12, 'i32') }}}
  3200. ];
  3201. addr = __inet_ntop6_raw(addr);
  3202. break;
  3203. default:
  3204. return { errno: {{{ cDefine('EAFNOSUPPORT') }}} };
  3205. }
  3206. return { family: family, addr: addr, port: port };
  3207. },
  3208. _write_sockaddr__deps: ['$Sockets', '_inet_pton4_raw', '_inet_pton6_raw'],
  3209. _write_sockaddr: function (sa, family, addr, port) {
  3210. switch (family) {
  3211. case {{{ cDefine('AF_INET') }}}:
  3212. addr = __inet_pton4_raw(addr);
  3213. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in.sin_family, 'family', 'i16') }}};
  3214. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in.sin_addr.s_addr, 'addr', 'i32') }}};
  3215. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in.sin_port, '_htons(port)', 'i16') }}};
  3216. break;
  3217. case {{{ cDefine('AF_INET6') }}}:
  3218. addr = __inet_pton6_raw(addr);
  3219. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_family, 'family', 'i32') }}};
  3220. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+0, 'addr[0]', 'i32') }}};
  3221. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+4, 'addr[1]', 'i32') }}};
  3222. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+8, 'addr[2]', 'i32') }}};
  3223. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+12, 'addr[3]', 'i32') }}};
  3224. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_port, '_htons(port)', 'i16') }}};
  3225. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_flowinfo, '0', 'i32') }}};
  3226. {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_scope_id, '0', 'i32') }}};
  3227. break;
  3228. default:
  3229. return { errno: {{{ cDefine('EAFNOSUPPORT') }}} };
  3230. }
  3231. // kind of lame, but let's match _read_sockaddr's interface
  3232. return {};
  3233. },
  3234. // We can't actually resolve hostnames in the browser, so instead
  3235. // we're generating fake IP addresses with lookup_name that we can
  3236. // resolve later on with lookup_addr.
  3237. // We do the aliasing in 172.29.*.*, giving us 65536 possibilities.
  3238. $DNS__deps: ['_inet_pton4_raw', '_inet_pton6_raw'],
  3239. $DNS: {
  3240. address_map: {
  3241. id: 1,
  3242. addrs: {},
  3243. names: {}
  3244. },
  3245. lookup_name: function (name) {
  3246. // If the name is already a valid ipv4 / ipv6 address, don't generate a fake one.
  3247. var res = __inet_pton4_raw(name);
  3248. if (res !== null) {
  3249. return name;
  3250. }
  3251. res = __inet_pton6_raw(name);
  3252. if (res !== null) {
  3253. return name;
  3254. }
  3255. // See if this name is already mapped.
  3256. var addr;
  3257. if (DNS.address_map.addrs[name]) {
  3258. addr = DNS.address_map.addrs[name];
  3259. } else {
  3260. var id = DNS.address_map.id++;
  3261. assert(id < 65535, 'exceeded max address mappings of 65535');
  3262. addr = '172.29.' + (id & 0xff) + '.' + (id & 0xff00);
  3263. DNS.address_map.names[addr] = name;
  3264. DNS.address_map.addrs[name] = addr;
  3265. }
  3266. return addr;
  3267. },
  3268. lookup_addr: function (addr) {
  3269. if (DNS.address_map.names[addr]) {
  3270. return DNS.address_map.names[addr];
  3271. }
  3272. return null;
  3273. }
  3274. },
  3275. // note: lots of leaking here!
  3276. gethostbyaddr__deps: ['$DNS', 'gethostbyname', '_inet_ntop4_raw'],
  3277. gethostbyaddr__proxy: 'sync',
  3278. gethostbyaddr__sig: 'iiii',
  3279. gethostbyaddr: function (addr, addrlen, type) {
  3280. if (type !== {{{ cDefine('AF_INET') }}}) {
  3281. setErrNo({{{ cDefine('EAFNOSUPPORT') }}});
  3282. // TODO: set h_errno
  3283. return null;
  3284. }
  3285. addr = {{{ makeGetValue('addr', '0', 'i32') }}}; // addr is in_addr
  3286. var host = __inet_ntop4_raw(addr);
  3287. var lookup = DNS.lookup_addr(host);
  3288. if (lookup) {
  3289. host = lookup;
  3290. }
  3291. var hostp = allocate(intArrayFromString(host), 'i8', ALLOC_STACK);
  3292. return _gethostbyname(hostp);
  3293. },
  3294. gethostbyname__deps: ['$DNS', '_inet_pton4_raw'],
  3295. gethostbyname__proxy: 'sync',
  3296. gethostbyname__sig: 'ii',
  3297. gethostbyname: function(name) {
  3298. name = UTF8ToString(name);
  3299. // generate hostent
  3300. var ret = _malloc({{{ C_STRUCTS.hostent.__size__ }}}); // XXX possibly leaked, as are others here
  3301. var nameBuf = _malloc(name.length+1);
  3302. stringToUTF8(name, nameBuf, name.length+1);
  3303. {{{ makeSetValue('ret', C_STRUCTS.hostent.h_name, 'nameBuf', 'i8*') }}};
  3304. var aliasesBuf = _malloc(4);
  3305. {{{ makeSetValue('aliasesBuf', '0', '0', 'i8*') }}};
  3306. {{{ makeSetValue('ret', C_STRUCTS.hostent.h_aliases, 'aliasesBuf', 'i8**') }}};
  3307. var afinet = {{{ cDefine('AF_INET') }}};
  3308. {{{ makeSetValue('ret', C_STRUCTS.hostent.h_addrtype, 'afinet', 'i32') }}};
  3309. {{{ makeSetValue('ret', C_STRUCTS.hostent.h_length, '4', 'i32') }}};
  3310. var addrListBuf = _malloc(12);
  3311. {{{ makeSetValue('addrListBuf', '0', 'addrListBuf+8', 'i32*') }}};
  3312. {{{ makeSetValue('addrListBuf', '4', '0', 'i32*') }}};
  3313. {{{ makeSetValue('addrListBuf', '8', '__inet_pton4_raw(DNS.lookup_name(name))', 'i32') }}};
  3314. {{{ makeSetValue('ret', C_STRUCTS.hostent.h_addr_list, 'addrListBuf', 'i8**') }}};
  3315. return ret;
  3316. },
  3317. gethostbyname_r__deps: ['gethostbyname'],
  3318. gethostbyname_r__proxy: 'sync',
  3319. gethostbyname_r__sig: 'iiiiiii',
  3320. gethostbyname_r: function(name, ret, buf, buflen, out, err) {
  3321. var data = _gethostbyname(name);
  3322. _memcpy(ret, data, {{{ C_STRUCTS.hostent.__size__ }}});
  3323. _free(data);
  3324. {{{ makeSetValue('err', '0', '0', 'i32') }}};
  3325. {{{ makeSetValue('out', '0', 'ret', '*') }}};
  3326. return 0;
  3327. },
  3328. getaddrinfo__deps: ['$Sockets', '$DNS', '_inet_pton4_raw', '_inet_ntop4_raw', '_inet_pton6_raw', '_inet_ntop6_raw', '_write_sockaddr'],
  3329. getaddrinfo__proxy: 'sync',
  3330. getaddrinfo__sig: 'iiiii',
  3331. getaddrinfo: function(node, service, hint, out) {
  3332. // Note getaddrinfo currently only returns a single addrinfo with ai_next defaulting to NULL. When NULL
  3333. // hints are specified or ai_family set to AF_UNSPEC or ai_socktype or ai_protocol set to 0 then we
  3334. // really should provide a linked list of suitable addrinfo values.
  3335. var addrs = [];
  3336. var canon = null;
  3337. var addr = 0;
  3338. var port = 0;
  3339. var flags = 0;
  3340. var family = {{{ cDefine('AF_UNSPEC') }}};
  3341. var type = 0;
  3342. var proto = 0;
  3343. var ai, last;
  3344. function allocaddrinfo(family, type, proto, canon, addr, port) {
  3345. var sa, salen, ai;
  3346. var res;
  3347. salen = family === {{{ cDefine('AF_INET6') }}} ?
  3348. {{{ C_STRUCTS.sockaddr_in6.__size__ }}} :
  3349. {{{ C_STRUCTS.sockaddr_in.__size__ }}};
  3350. addr = family === {{{ cDefine('AF_INET6') }}} ?
  3351. __inet_ntop6_raw(addr) :
  3352. __inet_ntop4_raw(addr);
  3353. sa = _malloc(salen);
  3354. res = __write_sockaddr(sa, family, addr, port);
  3355. assert(!res.errno);
  3356. ai = _malloc({{{ C_STRUCTS.addrinfo.__size__ }}});
  3357. {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_family, 'family', 'i32') }}};
  3358. {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_socktype, 'type', 'i32') }}};
  3359. {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_protocol, 'proto', 'i32') }}};
  3360. {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_canonname, 'canon', 'i32') }}};
  3361. {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_addr, 'sa', '*') }}};
  3362. if (family === {{{ cDefine('AF_INET6') }}}) {
  3363. {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_addrlen, C_STRUCTS.sockaddr_in6.__size__, 'i32') }}};
  3364. } else {
  3365. {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_addrlen, C_STRUCTS.sockaddr_in.__size__, 'i32') }}};
  3366. }
  3367. {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_next, '0', 'i32') }}};
  3368. return ai;
  3369. }
  3370. if (hint) {
  3371. flags = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_flags, 'i32') }}};
  3372. family = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_family, 'i32') }}};
  3373. type = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_socktype, 'i32') }}};
  3374. proto = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_protocol, 'i32') }}};
  3375. }
  3376. if (type && !proto) {
  3377. proto = type === {{{ cDefine('SOCK_DGRAM') }}} ? {{{ cDefine('IPPROTO_UDP') }}} : {{{ cDefine('IPPROTO_TCP') }}};
  3378. }
  3379. if (!type && proto) {
  3380. type = proto === {{{ cDefine('IPPROTO_UDP') }}} ? {{{ cDefine('SOCK_DGRAM') }}} : {{{ cDefine('SOCK_STREAM') }}};
  3381. }
  3382. // If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for
  3383. // now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints.
  3384. if (proto === 0) {
  3385. proto = {{{ cDefine('IPPROTO_TCP') }}};
  3386. }
  3387. if (type === 0) {
  3388. type = {{{ cDefine('SOCK_STREAM') }}};
  3389. }
  3390. if (!node && !service) {
  3391. return {{{ cDefine('EAI_NONAME') }}};
  3392. }
  3393. if (flags & ~({{{ cDefine('AI_PASSIVE') }}}|{{{ cDefine('AI_CANONNAME') }}}|{{{ cDefine('AI_NUMERICHOST') }}}|
  3394. {{{ cDefine('AI_NUMERICSERV') }}}|{{{ cDefine('AI_V4MAPPED') }}}|{{{ cDefine('AI_ALL') }}}|{{{ cDefine('AI_ADDRCONFIG') }}})) {
  3395. return {{{ cDefine('EAI_BADFLAGS') }}};
  3396. }
  3397. if (hint !== 0 && ({{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_flags, 'i32') }}} & {{{ cDefine('AI_CANONNAME') }}}) && !node) {
  3398. return {{{ cDefine('EAI_BADFLAGS') }}};
  3399. }
  3400. if (flags & {{{ cDefine('AI_ADDRCONFIG') }}}) {
  3401. // TODO
  3402. return {{{ cDefine('EAI_NONAME') }}};
  3403. }
  3404. if (type !== 0 && type !== {{{ cDefine('SOCK_STREAM') }}} && type !== {{{ cDefine('SOCK_DGRAM') }}}) {
  3405. return {{{ cDefine('EAI_SOCKTYPE') }}};
  3406. }
  3407. if (family !== {{{ cDefine('AF_UNSPEC') }}} && family !== {{{ cDefine('AF_INET') }}} && family !== {{{ cDefine('AF_INET6') }}}) {
  3408. return {{{ cDefine('EAI_FAMILY') }}};
  3409. }
  3410. if (service) {
  3411. service = UTF8ToString(service);
  3412. port = parseInt(service, 10);
  3413. if (isNaN(port)) {
  3414. if (flags & {{{ cDefine('AI_NUMERICSERV') }}}) {
  3415. return {{{ cDefine('EAI_NONAME') }}};
  3416. }
  3417. // TODO support resolving well-known service names from:
  3418. // http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
  3419. return {{{ cDefine('EAI_SERVICE') }}};
  3420. }
  3421. }
  3422. if (!node) {
  3423. if (family === {{{ cDefine('AF_UNSPEC') }}}) {
  3424. family = {{{ cDefine('AF_INET') }}};
  3425. }
  3426. if ((flags & {{{ cDefine('AI_PASSIVE') }}}) === 0) {
  3427. if (family === {{{ cDefine('AF_INET') }}}) {
  3428. addr = _htonl({{{ cDefine('INADDR_LOOPBACK') }}});
  3429. } else {
  3430. addr = [0, 0, 0, 1];
  3431. }
  3432. }
  3433. ai = allocaddrinfo(family, type, proto, null, addr, port);
  3434. {{{ makeSetValue('out', '0', 'ai', '*') }}};
  3435. return 0;
  3436. }
  3437. //
  3438. // try as a numeric address
  3439. //
  3440. node = UTF8ToString(node);
  3441. addr = __inet_pton4_raw(node);
  3442. if (addr !== null) {
  3443. // incoming node is a valid ipv4 address
  3444. if (family === {{{ cDefine('AF_UNSPEC') }}} || family === {{{ cDefine('AF_INET') }}}) {
  3445. family = {{{ cDefine('AF_INET') }}};
  3446. }
  3447. else if (family === {{{ cDefine('AF_INET6') }}} && (flags & {{{ cDefine('AI_V4MAPPED') }}})) {
  3448. addr = [0, 0, _htonl(0xffff), addr];
  3449. family = {{{ cDefine('AF_INET6') }}};
  3450. } else {
  3451. return {{{ cDefine('EAI_NONAME') }}};
  3452. }
  3453. } else {
  3454. addr = __inet_pton6_raw(node);
  3455. if (addr !== null) {
  3456. // incoming node is a valid ipv6 address
  3457. if (family === {{{ cDefine('AF_UNSPEC') }}} || family === {{{ cDefine('AF_INET6') }}}) {
  3458. family = {{{ cDefine('AF_INET6') }}};
  3459. } else {
  3460. return {{{ cDefine('EAI_NONAME') }}};
  3461. }
  3462. }
  3463. }
  3464. if (addr != null) {
  3465. ai = allocaddrinfo(family, type, proto, node, addr, port);
  3466. {{{ makeSetValue('out', '0', 'ai', '*') }}};
  3467. return 0;
  3468. }
  3469. if (flags & {{{ cDefine('AI_NUMERICHOST') }}}) {
  3470. return {{{ cDefine('EAI_NONAME') }}};
  3471. }
  3472. //
  3473. // try as a hostname
  3474. //
  3475. // resolve the hostname to a temporary fake address
  3476. node = DNS.lookup_name(node);
  3477. addr = __inet_pton4_raw(node);
  3478. if (family === {{{ cDefine('AF_UNSPEC') }}}) {
  3479. family = {{{ cDefine('AF_INET') }}};
  3480. } else if (family === {{{ cDefine('AF_INET6') }}}) {
  3481. addr = [0, 0, _htonl(0xffff), addr];
  3482. }
  3483. ai = allocaddrinfo(family, type, proto, null, addr, port);
  3484. {{{ makeSetValue('out', '0', 'ai', '*') }}};
  3485. return 0;
  3486. },
  3487. getnameinfo__deps: ['$Sockets', '$DNS', '_read_sockaddr'],
  3488. getnameinfo: function (sa, salen, node, nodelen, serv, servlen, flags) {
  3489. var info = __read_sockaddr(sa, salen);
  3490. if (info.errno) {
  3491. return {{{ cDefine('EAI_FAMILY') }}};
  3492. }
  3493. var port = info.port;
  3494. var addr = info.addr;
  3495. var overflowed = false;
  3496. if (node && nodelen) {
  3497. var lookup;
  3498. if ((flags & {{{ cDefine('NI_NUMERICHOST') }}}) || !(lookup = DNS.lookup_addr(addr))) {
  3499. if (flags & {{{ cDefine('NI_NAMEREQD') }}}) {
  3500. return {{{ cDefine('EAI_NONAME') }}};
  3501. }
  3502. } else {
  3503. addr = lookup;
  3504. }
  3505. var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen);
  3506. if (numBytesWrittenExclNull+1 >= nodelen) {
  3507. overflowed = true;
  3508. }
  3509. }
  3510. if (serv && servlen) {
  3511. port = '' + port;
  3512. var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen);
  3513. if (numBytesWrittenExclNull+1 >= servlen) {
  3514. overflowed = true;
  3515. }
  3516. }
  3517. if (overflowed) {
  3518. // Note: even when we overflow, getnameinfo() is specced to write out the truncated results.
  3519. return {{{ cDefine('EAI_OVERFLOW') }}};
  3520. }
  3521. return 0;
  3522. },
  3523. // Can't use a literal for $GAI_ERRNO_MESSAGES as was done for $ERRNO_MESSAGES as the keys (e.g. EAI_BADFLAGS)
  3524. // are actually negative numbers and you can't have expressions as keys in JavaScript literals.
  3525. $GAI_ERRNO_MESSAGES: {},
  3526. gai_strerror__deps: ['$GAI_ERRNO_MESSAGES'],
  3527. gai_strerror: function(val) {
  3528. var buflen = 256;
  3529. // On first call to gai_strerror we initialise the buffer and populate the error messages.
  3530. if (!_gai_strerror.buffer) {
  3531. _gai_strerror.buffer = _malloc(buflen);
  3532. GAI_ERRNO_MESSAGES['0'] = 'Success';
  3533. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_BADFLAGS') }}}] = 'Invalid value for \'ai_flags\' field';
  3534. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_NONAME') }}}] = 'NAME or SERVICE is unknown';
  3535. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_AGAIN') }}}] = 'Temporary failure in name resolution';
  3536. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_FAIL') }}}] = 'Non-recoverable failure in name res';
  3537. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_FAMILY') }}}] = '\'ai_family\' not supported';
  3538. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_SOCKTYPE') }}}] = '\'ai_socktype\' not supported';
  3539. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_SERVICE') }}}] = 'SERVICE not supported for \'ai_socktype\'';
  3540. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_MEMORY') }}}] = 'Memory allocation failure';
  3541. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_SYSTEM') }}}] = 'System error returned in \'errno\'';
  3542. GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_OVERFLOW') }}}] = 'Argument buffer overflow';
  3543. }
  3544. var msg = 'Unknown error';
  3545. if (val in GAI_ERRNO_MESSAGES) {
  3546. if (GAI_ERRNO_MESSAGES[val].length > buflen - 1) {
  3547. msg = 'Message too long'; // EMSGSIZE message. This should never occur given the GAI_ERRNO_MESSAGES above.
  3548. } else {
  3549. msg = GAI_ERRNO_MESSAGES[val];
  3550. }
  3551. }
  3552. writeAsciiToMemory(msg, _gai_strerror.buffer);
  3553. return _gai_strerror.buffer;
  3554. },
  3555. // Implement netdb.h protocol entry (getprotoent, getprotobyname, getprotobynumber, setprotoent, endprotoent)
  3556. // http://pubs.opengroup.org/onlinepubs/9699919799/functions/getprotobyname.html
  3557. // The Protocols object holds our 'fake' protocols 'database'.
  3558. $Protocols: {
  3559. list: [],
  3560. map: {}
  3561. },
  3562. setprotoent__deps: ['$Protocols'],
  3563. setprotoent: function(stayopen) {
  3564. // void setprotoent(int stayopen);
  3565. // Allocate and populate a protoent structure given a name, protocol number and array of aliases
  3566. function allocprotoent(name, proto, aliases) {
  3567. // write name into buffer
  3568. var nameBuf = _malloc(name.length + 1);
  3569. writeAsciiToMemory(name, nameBuf);
  3570. // write aliases into buffer
  3571. var j = 0;
  3572. var length = aliases.length;
  3573. var aliasListBuf = _malloc((length + 1) * 4); // Use length + 1 so we have space for the terminating NULL ptr.
  3574. for (var i = 0; i < length; i++, j += 4) {
  3575. var alias = aliases[i];
  3576. var aliasBuf = _malloc(alias.length + 1);
  3577. writeAsciiToMemory(alias, aliasBuf);
  3578. {{{ makeSetValue('aliasListBuf', 'j', 'aliasBuf', 'i8*') }}};
  3579. }
  3580. {{{ makeSetValue('aliasListBuf', 'j', '0', 'i8*') }}}; // Terminating NULL pointer.
  3581. // generate protoent
  3582. var pe = _malloc({{{ C_STRUCTS.protoent.__size__ }}});
  3583. {{{ makeSetValue('pe', C_STRUCTS.protoent.p_name, 'nameBuf', 'i8*') }}};
  3584. {{{ makeSetValue('pe', C_STRUCTS.protoent.p_aliases, 'aliasListBuf', 'i8**') }}};
  3585. {{{ makeSetValue('pe', C_STRUCTS.protoent.p_proto, 'proto', 'i32') }}};
  3586. return pe;
  3587. };
  3588. // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial
  3589. // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful.
  3590. var list = Protocols.list;
  3591. var map = Protocols.map;
  3592. if (list.length === 0) {
  3593. var entry = allocprotoent('tcp', 6, ['TCP']);
  3594. list.push(entry);
  3595. map['tcp'] = map['6'] = entry;
  3596. entry = allocprotoent('udp', 17, ['UDP']);
  3597. list.push(entry);
  3598. map['udp'] = map['17'] = entry;
  3599. }
  3600. _setprotoent.index = 0;
  3601. },
  3602. endprotoent: function() {
  3603. // void endprotoent(void);
  3604. // We're not using a real protocol database so we don't do a real close.
  3605. },
  3606. getprotoent__deps: ['setprotoent', '$Protocols'],
  3607. getprotoent: function(number) {
  3608. // struct protoent *getprotoent(void);
  3609. // reads the next entry from the protocols 'database' or return NULL if 'eof'
  3610. if (_setprotoent.index === Protocols.list.length) {
  3611. return 0;
  3612. } else {
  3613. var result = Protocols.list[_setprotoent.index++];
  3614. return result;
  3615. }
  3616. },
  3617. getprotobyname__deps: ['setprotoent', '$Protocols'],
  3618. getprotobyname: function(name) {
  3619. // struct protoent *getprotobyname(const char *);
  3620. name = UTF8ToString(name);
  3621. _setprotoent(true);
  3622. var result = Protocols.map[name];
  3623. return result;
  3624. },
  3625. getprotobynumber__deps: ['setprotoent', '$Protocols'],
  3626. getprotobynumber: function(number) {
  3627. // struct protoent *getprotobynumber(int proto);
  3628. _setprotoent(true);
  3629. var result = Protocols.map[number];
  3630. return result;
  3631. },
  3632. // ==========================================================================
  3633. // sockets. Note that the implementation assumes all sockets are always
  3634. // nonblocking
  3635. // ==========================================================================
  3636. #if SOCKET_WEBRTC
  3637. $Sockets__deps: ['$setErrNo',
  3638. function() { return 'var SocketIO = ' + read('socket.io.js') + ';\n' },
  3639. function() { return 'var Peer = ' + read('wrtcp.js') + ';\n' }],
  3640. #else
  3641. $Sockets__deps: ['$setErrNo'],
  3642. #endif
  3643. $Sockets: {
  3644. BUFFER_SIZE: 10*1024, // initial size
  3645. MAX_BUFFER_SIZE: 10*1024*1024, // maximum size we will grow the buffer
  3646. nextFd: 1,
  3647. fds: {},
  3648. nextport: 1,
  3649. maxport: 65535,
  3650. peer: null,
  3651. connections: {},
  3652. portmap: {},
  3653. localAddr: 0xfe00000a, // Local address is always 10.0.0.254
  3654. addrPool: [ 0x0200000a, 0x0300000a, 0x0400000a, 0x0500000a,
  3655. 0x0600000a, 0x0700000a, 0x0800000a, 0x0900000a, 0x0a00000a,
  3656. 0x0b00000a, 0x0c00000a, 0x0d00000a, 0x0e00000a] /* 0x0100000a is reserved */
  3657. },
  3658. #endif // PROXY_POSIX_SOCKETS == 0
  3659. // pwd.h
  3660. getpwnam: function() { throw 'getpwnam: TODO' },
  3661. getpwnam_r: function() { throw 'getpwnam_r: TODO' },
  3662. getpwuid: function() { throw 'getpwuid: TODO' },
  3663. getpwuid_r: function() { throw 'getpwuid_r: TODO' },
  3664. setpwent: function() { throw 'setpwent: TODO' },
  3665. getpwent: function() { throw 'getpwent: TODO' },
  3666. endpwent: function() { throw 'endpwent: TODO' },
  3667. // grp.h
  3668. getgrgid: function() { throw 'getgrgid: TODO' },
  3669. getgrgid_r: function() { throw 'getgrgid_r: TODO' },
  3670. getgrnam: function() { throw 'getgrnam: TODO' },
  3671. getgrnam_r: function() { throw 'getgrnam_r: TODO' },
  3672. getgrent: function() { throw 'getgrent: TODO' },
  3673. endgrent: function() { throw 'endgrent: TODO' },
  3674. setgrent: function() { throw 'setgrent: TODO' },
  3675. // ==========================================================================
  3676. // emscripten.h
  3677. // ==========================================================================
  3678. emscripten_run_script: function(ptr) {
  3679. {{{ makeEval('eval(UTF8ToString(ptr));') }}}
  3680. },
  3681. emscripten_run_script_int__docs: '/** @suppress{checkTypes} */',
  3682. emscripten_run_script_int: function(ptr) {
  3683. {{{ makeEval('return eval(UTF8ToString(ptr))|0;') }}}
  3684. },
  3685. emscripten_run_script_string: function(ptr) {
  3686. {{{ makeEval("var s = eval(UTF8ToString(ptr));") }}}
  3687. if (s == null) {
  3688. return 0;
  3689. }
  3690. s += '';
  3691. var me = _emscripten_run_script_string;
  3692. var len = lengthBytesUTF8(s);
  3693. if (!me.bufferSize || me.bufferSize < len+1) {
  3694. if (me.bufferSize) _free(me.buffer);
  3695. me.bufferSize = len+1;
  3696. me.buffer = _malloc(me.bufferSize);
  3697. }
  3698. stringToUTF8(s, me.buffer, me.bufferSize);
  3699. return me.buffer;
  3700. },
  3701. emscripten_random: function() {
  3702. return Math.random();
  3703. },
  3704. emscripten_get_now__import: true,
  3705. emscripten_get_now: ';' +
  3706. #if ENVIRONMENT_MAY_BE_NODE
  3707. "if (ENVIRONMENT_IS_NODE) {\n" +
  3708. " _emscripten_get_now = function() {\n" +
  3709. " var t = process['hrtime']();\n" +
  3710. " return t[0] * 1e3 + t[1] / 1e6;\n" +
  3711. " };\n" +
  3712. "} else " +
  3713. #endif
  3714. #if USE_PTHREADS
  3715. // Pthreads need their clocks synchronized to the execution of the main thread, so give them a special form of the function.
  3716. "if (ENVIRONMENT_IS_PTHREAD) {\n" +
  3717. " _emscripten_get_now = function() { return performance.now() - Module['__performance_now_clock_drift']; };\n" +
  3718. "} else " +
  3719. #endif
  3720. #if ENVIRONMENT_MAY_BE_SHELL
  3721. "if (typeof dateNow !== 'undefined') {\n" +
  3722. " _emscripten_get_now = dateNow;\n" +
  3723. "} else " +
  3724. #endif
  3725. #if MIN_IE_VERSION <= 9 || MIN_FIREFOX_VERSION <= 14 || MIN_CHROME_VERSION <= 23 || MIN_SAFARI_VERSION <= 80400 // https://caniuse.com/#feat=high-resolution-time
  3726. "if (typeof performance !== 'undefined' && performance.now) {\n" +
  3727. " _emscripten_get_now = function() { return performance.now(); }\n" +
  3728. "} else {\n" +
  3729. " _emscripten_get_now = Date.now;\n" +
  3730. "}",
  3731. #else
  3732. // Modern environment where performance.now() is supported:
  3733. // N.B. a shorter form "_emscripten_get_now = return performance.now;" is unfortunately not allowed even in current browsers (e.g. FF Nightly 75).
  3734. "_emscripten_get_now = function() { return performance.now(); }\n",
  3735. #endif
  3736. emscripten_get_now_res: function() { // return resolution of get_now, in nanoseconds
  3737. #if ENVIRONMENT_MAY_BE_NODE
  3738. if (ENVIRONMENT_IS_NODE) {
  3739. return 1; // nanoseconds
  3740. } else
  3741. #endif
  3742. #if ENVIRONMENT_MAY_BE_SHELL
  3743. if (typeof dateNow !== 'undefined') {
  3744. return 1000; // microseconds (1/1000 of a millisecond)
  3745. } else
  3746. #endif
  3747. #if MIN_IE_VERSION <= 9 || MIN_FIREFOX_VERSION <= 14 || MIN_CHROME_VERSION <= 23 || MIN_SAFARI_VERSION <= 80400 // https://caniuse.com/#feat=high-resolution-time
  3748. if (typeof performance === 'object' && performance && typeof performance['now'] === 'function') {
  3749. return 1000; // microseconds (1/1000 of a millisecond)
  3750. } else {
  3751. return 1000*1000; // milliseconds
  3752. }
  3753. #else
  3754. // Modern environment where performance.now() is supported:
  3755. return 1000; // microseconds (1/1000 of a millisecond)
  3756. #endif
  3757. },
  3758. // Represents whether emscripten_get_now is guaranteed monotonic; the Date.now
  3759. // implementation is not :(
  3760. #if MIN_IE_VERSION <= 9 || MIN_FIREFOX_VERSION <= 14 || MIN_CHROME_VERSION <= 23 || MIN_SAFARI_VERSION <= 80400 // https://caniuse.com/#feat=high-resolution-time
  3761. emscripten_get_now_is_monotonic: `
  3762. ((typeof performance === 'object' && performance && typeof performance['now'] === 'function')
  3763. #if ENVIRONMENT_MAY_BE_NODE
  3764. || ENVIRONMENT_IS_NODE
  3765. #endif
  3766. #if ENVIRONMENT_MAY_BE_SHELL
  3767. || (typeof dateNow !== 'undefined')
  3768. #endif
  3769. );`,
  3770. #else
  3771. // Modern environment where performance.now() is supported: (rely on minifier to return true unconditionally from this function)
  3772. emscripten_get_now_is_monotonic: 'true;',
  3773. #endif
  3774. #if MINIMAL_RUNTIME
  3775. $warnOnce: function(text) {
  3776. if (!warnOnce.shown) warnOnce.shown = {};
  3777. if (!warnOnce.shown[text]) {
  3778. warnOnce.shown[text] = 1;
  3779. err(text);
  3780. }
  3781. },
  3782. #endif
  3783. // Returns [parentFuncArguments, functionName, paramListName]
  3784. _emscripten_traverse_stack: function(args) {
  3785. if (!args || !args.callee || !args.callee.name) {
  3786. return [null, '', ''];
  3787. }
  3788. var funstr = args.callee.toString();
  3789. var funcname = args.callee.name;
  3790. var str = '(';
  3791. var first = true;
  3792. for (var i in args) {
  3793. var a = args[i];
  3794. if (!first) {
  3795. str += ", ";
  3796. }
  3797. first = false;
  3798. if (typeof a === 'number' || typeof a === 'string') {
  3799. str += a;
  3800. } else {
  3801. str += '(' + typeof a + ')';
  3802. }
  3803. }
  3804. str += ')';
  3805. var caller = args.callee.caller;
  3806. args = caller ? caller.arguments : [];
  3807. if (first)
  3808. str = '';
  3809. return [args, funcname, str];
  3810. },
  3811. emscripten_get_callstack_js__deps: ['_emscripten_traverse_stack', '$jsStackTrace', '$demangle'
  3812. #if MINIMAL_RUNTIME
  3813. , '$warnOnce'
  3814. #endif
  3815. ],
  3816. emscripten_get_callstack_js__docs: '/** @param {number=} flags */',
  3817. emscripten_get_callstack_js: function(flags) {
  3818. var callstack = jsStackTrace();
  3819. // Find the symbols in the callstack that corresponds to the functions that report callstack information, and remove everything up to these from the output.
  3820. var iThisFunc = callstack.lastIndexOf('_emscripten_log');
  3821. var iThisFunc2 = callstack.lastIndexOf('_emscripten_get_callstack');
  3822. var iNextLine = callstack.indexOf('\n', Math.max(iThisFunc, iThisFunc2))+1;
  3823. callstack = callstack.slice(iNextLine);
  3824. // If user requested to see the original source stack, but no source map information is available, just fall back to showing the JS stack.
  3825. if (flags & 8/*EM_LOG_C_STACK*/ && typeof emscripten_source_map === 'undefined') {
  3826. warnOnce('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.');
  3827. flags ^= 8/*EM_LOG_C_STACK*/;
  3828. flags |= 16/*EM_LOG_JS_STACK*/;
  3829. }
  3830. var stack_args = null;
  3831. if (flags & 128 /*EM_LOG_FUNC_PARAMS*/) {
  3832. // To get the actual parameters to the functions, traverse the stack via the unfortunately deprecated 'arguments.callee' method, if it works:
  3833. stack_args = __emscripten_traverse_stack(arguments);
  3834. while (stack_args[1].indexOf('_emscripten_') >= 0)
  3835. stack_args = __emscripten_traverse_stack(stack_args[0]);
  3836. }
  3837. // Process all lines:
  3838. var lines = callstack.split('\n');
  3839. callstack = '';
  3840. var newFirefoxRe = new RegExp('\\s*(.*?)@(.*?):([0-9]+):([0-9]+)'); // New FF30 with column info: extract components of form ' Object._main@http://server.com:4324:12'
  3841. var firefoxRe = new RegExp('\\s*(.*?)@(.*):(.*)(:(.*))?'); // Old FF without column info: extract components of form ' Object._main@http://server.com:4324'
  3842. var chromeRe = new RegExp('\\s*at (.*?) \\\((.*):(.*):(.*)\\\)'); // Extract components of form ' at Object._main (http://server.com/file.html:4324:12)'
  3843. for (var l in lines) {
  3844. var line = lines[l];
  3845. var jsSymbolName = '';
  3846. var file = '';
  3847. var lineno = 0;
  3848. var column = 0;
  3849. var parts = chromeRe.exec(line);
  3850. if (parts && parts.length == 5) {
  3851. jsSymbolName = parts[1];
  3852. file = parts[2];
  3853. lineno = parts[3];
  3854. column = parts[4];
  3855. } else {
  3856. parts = newFirefoxRe.exec(line);
  3857. if (!parts) parts = firefoxRe.exec(line);
  3858. if (parts && parts.length >= 4) {
  3859. jsSymbolName = parts[1];
  3860. file = parts[2];
  3861. lineno = parts[3];
  3862. column = parts[4]|0; // Old Firefox doesn't carry column information, but in new FF30, it is present. See https://bugzilla.mozilla.org/show_bug.cgi?id=762556
  3863. } else {
  3864. // Was not able to extract this line for demangling/sourcemapping purposes. Output it as-is.
  3865. callstack += line + '\n';
  3866. continue;
  3867. }
  3868. }
  3869. // Try to demangle the symbol, but fall back to showing the original JS symbol name if not available.
  3870. var cSymbolName = (flags & 32/*EM_LOG_DEMANGLE*/) ? demangle(jsSymbolName) : jsSymbolName;
  3871. if (!cSymbolName) {
  3872. cSymbolName = jsSymbolName;
  3873. }
  3874. var haveSourceMap = false;
  3875. if (flags & 8/*EM_LOG_C_STACK*/) {
  3876. var orig = emscripten_source_map.originalPositionFor({line: lineno, column: column});
  3877. haveSourceMap = (orig && orig.source);
  3878. if (haveSourceMap) {
  3879. if (flags & 64/*EM_LOG_NO_PATHS*/) {
  3880. orig.source = orig.source.substring(orig.source.replace(/\\/g, "/").lastIndexOf('/')+1);
  3881. }
  3882. callstack += ' at ' + cSymbolName + ' (' + orig.source + ':' + orig.line + ':' + orig.column + ')\n';
  3883. }
  3884. }
  3885. if ((flags & 16/*EM_LOG_JS_STACK*/) || !haveSourceMap) {
  3886. if (flags & 64/*EM_LOG_NO_PATHS*/) {
  3887. file = file.substring(file.replace(/\\/g, "/").lastIndexOf('/')+1);
  3888. }
  3889. callstack += (haveSourceMap ? (' = '+jsSymbolName) : (' at '+cSymbolName)) + ' (' + file + ':' + lineno + ':' + column + ')\n';
  3890. }
  3891. // If we are still keeping track with the callstack by traversing via 'arguments.callee', print the function parameters as well.
  3892. if (flags & 128 /*EM_LOG_FUNC_PARAMS*/ && stack_args[0]) {
  3893. if (stack_args[1] == jsSymbolName && stack_args[2].length > 0) {
  3894. callstack = callstack.replace(/\s+$/, '');
  3895. callstack += ' with values: ' + stack_args[1] + stack_args[2] + '\n';
  3896. }
  3897. stack_args = __emscripten_traverse_stack(stack_args[0]);
  3898. }
  3899. }
  3900. // Trim extra whitespace at the end of the output.
  3901. callstack = callstack.replace(/\s+$/, '');
  3902. return callstack;
  3903. },
  3904. emscripten_get_callstack__deps: ['emscripten_get_callstack_js'],
  3905. emscripten_get_callstack: function(flags, str, maxbytes) {
  3906. var callstack = _emscripten_get_callstack_js(flags);
  3907. // User can query the required amount of bytes to hold the callstack.
  3908. if (!str || maxbytes <= 0) {
  3909. return lengthBytesUTF8(callstack)+1;
  3910. }
  3911. // Output callstack string as C string to HEAP.
  3912. var bytesWrittenExcludingNull = stringToUTF8(callstack, str, maxbytes);
  3913. // Return number of bytes written, including null.
  3914. return bytesWrittenExcludingNull+1;
  3915. },
  3916. emscripten_log_js__deps: ['emscripten_get_callstack_js'],
  3917. emscripten_log_js: function(flags, str) {
  3918. if (flags & 24/*EM_LOG_C_STACK | EM_LOG_JS_STACK*/) {
  3919. str = str.replace(/\s+$/, ''); // Ensure the message and the callstack are joined cleanly with exactly one newline.
  3920. str += (str.length > 0 ? '\n' : '') + _emscripten_get_callstack_js(flags);
  3921. }
  3922. if (flags & 1 /*EM_LOG_CONSOLE*/) {
  3923. if (flags & 4 /*EM_LOG_ERROR*/) {
  3924. console.error(str);
  3925. } else if (flags & 2 /*EM_LOG_WARN*/) {
  3926. console.warn(str);
  3927. } else if (flags & 512 /*EM_LOG_INFO*/) {
  3928. console.info(str);
  3929. } else if (flags & 256 /*EM_LOG_DEBUG*/) {
  3930. console.debug(str);
  3931. } else {
  3932. console.log(str);
  3933. }
  3934. } else if (flags & 6 /*EM_LOG_ERROR|EM_LOG_WARN*/) {
  3935. err(str);
  3936. } else {
  3937. out(str);
  3938. }
  3939. },
  3940. emscripten_log__deps: ['$formatString', 'emscripten_log_js'],
  3941. emscripten_log: function(flags, format, varargs) {
  3942. var str = '';
  3943. var result = formatString(format, varargs);
  3944. for (var i = 0 ; i < result.length; ++i) {
  3945. str += String.fromCharCode(result[i]);
  3946. }
  3947. _emscripten_log_js(flags, str);
  3948. },
  3949. emscripten_get_compiler_setting: function(name) {
  3950. name = UTF8ToString(name);
  3951. var ret = getCompilerSetting(name);
  3952. if (typeof ret === 'number') return ret;
  3953. if (!_emscripten_get_compiler_setting.cache) _emscripten_get_compiler_setting.cache = {};
  3954. var cache = _emscripten_get_compiler_setting.cache;
  3955. var fullname = name + '__str';
  3956. var fullret = cache[fullname];
  3957. if (fullret) return fullret;
  3958. return cache[fullname] = allocate(intArrayFromString(ret + ''), 'i8', ALLOC_NORMAL);
  3959. },
  3960. emscripten_has_asyncify: function() {
  3961. return {{{ ASYNCIFY || EMTERPRETIFY_ASYNC }}};
  3962. },
  3963. emscripten_debugger: function() {
  3964. debugger;
  3965. },
  3966. emscripten_print_double: function(x, to, max) {
  3967. var str = x + '';
  3968. if (to) return stringToUTF8(str, to, max);
  3969. else return lengthBytesUTF8(str);
  3970. },
  3971. // Generates a representation of the program counter from a line of stack trace.
  3972. // The exact return value depends in whether we are running WASM or JS, and whether
  3973. // the engine supports offsets into WASM. See the function body for details.
  3974. emscripten_generate_pc: function(frame) {
  3975. #if !USE_OFFSET_CONVERTER
  3976. abort('Cannot use emscripten_generate_pc (needed by __builtin_return_address) without -s USE_OFFSET_CONVERTER');
  3977. #endif
  3978. var match;
  3979. if (match = /\bwasm-function\[\d+\]:(0x[0-9a-f]+)/.exec(frame)) {
  3980. // some engines give the binary offset directly, so we use that as return address
  3981. return +match[1];
  3982. } else if (match = /\bwasm-function\[(\d+)\]:(\d+)/.exec(frame)) {
  3983. // other engines only give function index and offset in the function,
  3984. // so we try using the offset converter. If that doesn't work,
  3985. // we pack index and offset into a "return address"
  3986. return wasmOffsetConverter.convert(+match[1], +match[2]);
  3987. } else if (match = /:(\d+):\d+(?:\)|$)/.exec(frame)) {
  3988. // if we are in js, we can use the js line number as the "return address"
  3989. // this should work for wasm2js and fastcomp
  3990. // we tag the high bit to distinguish this from wasm addresses
  3991. return 0x80000000 | +match[1];
  3992. } else {
  3993. // return 0 if we can't find any
  3994. return 0;
  3995. }
  3996. },
  3997. // Returns a representation of a call site of the caller of this function, in a manner
  3998. // similar to __builtin_return_address. If level is 0, we return the call site of the
  3999. // caller of this function.
  4000. emscripten_return_address__deps: ['emscripten_generate_pc'],
  4001. emscripten_return_address: function(level) {
  4002. var callstack = new Error().stack.split('\n');
  4003. if (callstack[0] == 'Error') {
  4004. callstack.shift();
  4005. }
  4006. // skip this function and the caller to get caller's return address
  4007. return _emscripten_generate_pc(callstack[level + 2]);
  4008. },
  4009. $UNWIND_CACHE: {},
  4010. // This function pulls the JavaScript stack trace and updates UNWIND_CACHE so that
  4011. // our representation of the program counter is mapped to the line of the stack trace
  4012. // for every line in the stack trace. This allows emscripten_pc_get_* to lookup the
  4013. // line of the stack trace from the PC and return meaningful information.
  4014. //
  4015. // Additionally, it saves a copy of the entire stack trace and the return address of
  4016. // the caller. This is because there are two common forms of a stack trace.
  4017. // The first form starts the stack trace at the caller of the function requesting a stack
  4018. // trace. In this case, the function can simply walk down the stack from the return address
  4019. // using emscripten_return_address with increasing values for level.
  4020. // The second form starts the stack trace at the current function. This requires a helper
  4021. // function to get the program counter. This helper function will return the return address.
  4022. // This is the program counter at the call site. But there is a problem: when calling into
  4023. // code that performs stack unwinding, the program counter has changed since execution
  4024. // continued from calling the helper function. So we can't just walk down the stack and expect
  4025. // to see.the PC value we got. By caching the call stack, we can call emscripten_stack_unwind
  4026. // with the PC value and use that to unwind the cached stack. Naturally, the PC helper function
  4027. // will have to call emscripten_stack_snapshot to cache the stack. We also return the return
  4028. // address of the caller so the PC helper function does not need to call
  4029. // emscripten_return_address, saving a lot of time.
  4030. //
  4031. // One might expect that a sensible solution is to call the stack unwinder and explicitly tell it
  4032. // how many functions to skip from the stack. However, existing libraries do not work this way.
  4033. // For example, compiler-rt's sanitizer_common library has macros GET_CALLER_PC_BP_SP and
  4034. // GET_CURRENT_PC_BP_SP, which obtains the PC value for the two common cases stated above,
  4035. // respectively. Then, it passes the PC, BP, SP values along until some other function uses them
  4036. // to unwind. On standard machines, the stack can be unwound by treating BP as a linked list.
  4037. // This makes PC unnecessary to walk the stack, since walking is done with BP, which remains
  4038. // valid until the function returns. But on Emscripten, BP does not exist, at least in
  4039. // JavaScript frames, so we have to rely on PC values. Therefore, we must be able to unwind from
  4040. // a PC value that may no longer be on the execution stack, and so we are forced to cache the
  4041. // entire call stack.
  4042. emscripten_stack_snapshot__deps: ['emscripten_generate_pc', '$UNWIND_CACHE', '_emscripten_save_in_unwind_cache'],
  4043. emscripten_stack_snapshot: function () {
  4044. var callstack = new Error().stack.split('\n');
  4045. if (callstack[0] == 'Error') {
  4046. callstack.shift();
  4047. }
  4048. __emscripten_save_in_unwind_cache(callstack);
  4049. // Caches the stack snapshot so that emscripten_stack_unwind_buffer() can unwind from this spot.
  4050. UNWIND_CACHE.last_addr = _emscripten_generate_pc(callstack[2]);
  4051. UNWIND_CACHE.last_stack = callstack;
  4052. return UNWIND_CACHE.last_addr;
  4053. },
  4054. _emscripten_save_in_unwind_cache__deps: ['$UNWIND_CACHE', 'emscripten_generate_pc'],
  4055. _emscripten_save_in_unwind_cache: function (callstack) {
  4056. callstack.forEach(function (frame) {
  4057. var pc = _emscripten_generate_pc(frame);
  4058. if (pc) {
  4059. UNWIND_CACHE[pc] = frame;
  4060. }
  4061. });
  4062. },
  4063. // Unwinds the stack from a cached PC value. See emscripten_stack_snapshot for how this is used.
  4064. // addr must be the return address of the last call to emscripten_stack_snapshot, or this
  4065. // function will instead use the current call stack.
  4066. emscripten_stack_unwind_buffer__deps: ['$UNWIND_CACHE', '_emscripten_save_in_unwind_cache', 'emscripten_generate_pc'],
  4067. emscripten_stack_unwind_buffer: function (addr, buffer, count) {
  4068. var stack;
  4069. if (UNWIND_CACHE.last_addr == addr) {
  4070. stack = UNWIND_CACHE.last_stack;
  4071. } else {
  4072. stack = new Error().stack.split('\n');
  4073. if (stack[0] == 'Error') {
  4074. stack.shift();
  4075. }
  4076. __emscripten_save_in_unwind_cache(stack);
  4077. }
  4078. var offset = 2;
  4079. while (stack[offset] && _emscripten_generate_pc(stack[offset]) != addr) {
  4080. ++offset;
  4081. }
  4082. for (var i = 0; i < count && stack[i+offset]; ++i) {
  4083. {{{ makeSetValue('buffer', 'i*4', '_emscripten_generate_pc(stack[i + offset])', 'i32', 0, true) }}};
  4084. }
  4085. return i;
  4086. },
  4087. // Look up the function name from our stack frame cache with our PC representation.
  4088. emscripten_pc_get_function__deps: ['$UNWIND_CACHE', 'emscripten_with_builtin_malloc'
  4089. #if MINIMAL_RUNTIME
  4090. , '$allocateUTF8'
  4091. #endif
  4092. ],
  4093. emscripten_pc_get_function: function (pc) {
  4094. #if !USE_OFFSET_CONVERTER
  4095. abort('Cannot use emscripten_pc_get_function without -s USE_OFFSET_CONVERTER');
  4096. #endif
  4097. var name;
  4098. if (pc & 0x80000000) {
  4099. // If this is a JavaScript function, try looking it up in the unwind cache.
  4100. var frame = UNWIND_CACHE[pc];
  4101. if (!frame) return 0;
  4102. var match;
  4103. if (match = /^\s+at (.*) \(.*\)$/.exec(frame)) {
  4104. name = match[1];
  4105. } else if (match = /^(.+?)@/.exec(frame)) {
  4106. name = match[1];
  4107. } else {
  4108. return 0;
  4109. }
  4110. } else {
  4111. name = wasmOffsetConverter.getName(pc);
  4112. }
  4113. _emscripten_with_builtin_malloc(function () {
  4114. if (_emscripten_pc_get_function.ret) _free(_emscripten_pc_get_function.ret);
  4115. _emscripten_pc_get_function.ret = allocateUTF8(name);
  4116. });
  4117. return _emscripten_pc_get_function.ret;
  4118. },
  4119. emscripten_pc_get_source_js__deps: ['$UNWIND_CACHE', 'emscripten_generate_pc'],
  4120. emscripten_pc_get_source_js: function (pc) {
  4121. if (UNWIND_CACHE.last_get_source_pc == pc) return UNWIND_CACHE.last_source;
  4122. var match;
  4123. var source;
  4124. #if LOAD_SOURCE_MAP
  4125. if (wasmSourceMap) {
  4126. var info = wasmSourceMap.lookup(pc);
  4127. if (info) {
  4128. source = {file: info.source, line: info.line, column: info.column};
  4129. }
  4130. }
  4131. #endif
  4132. if (!source) {
  4133. var frame = UNWIND_CACHE[pc];
  4134. if (!frame) return null;
  4135. // Example: at callMain (a.out.js:6335:22)
  4136. if (match = /\((.*):(\d+):(\d+)\)$/.exec(frame)) {
  4137. source = {file: match[1], line: match[2], column: match[3]};
  4138. // Example: main@a.out.js:1337:42
  4139. } else if (match = /@(.*):(\d+):(\d+)/.exec(frame)) {
  4140. source = {file: match[1], line: match[2], column: match[3]};
  4141. }
  4142. }
  4143. UNWIND_CACHE.last_get_source_pc = pc;
  4144. UNWIND_CACHE.last_source = source;
  4145. return source;
  4146. },
  4147. // Look up the file name from our stack frame cache with our PC representation.
  4148. emscripten_pc_get_file__deps: ['emscripten_pc_get_source_js', 'emscripten_with_builtin_malloc',
  4149. #if MINIMAL_RUNTIME
  4150. '$allocateUTF8',
  4151. #endif
  4152. ],
  4153. emscripten_pc_get_file: function (pc) {
  4154. var result = _emscripten_pc_get_source_js(pc);
  4155. if (!result) return 0;
  4156. _emscripten_with_builtin_malloc(function () {
  4157. if (_emscripten_pc_get_file.ret) _free(_emscripten_pc_get_file.ret);
  4158. _emscripten_pc_get_file.ret = allocateUTF8(result.file);
  4159. });
  4160. return _emscripten_pc_get_file.ret;
  4161. },
  4162. // Look up the line number from our stack frame cache with our PC representation.
  4163. emscripten_pc_get_line__deps: ['emscripten_pc_get_source_js'],
  4164. emscripten_pc_get_line: function (pc) {
  4165. var result = _emscripten_pc_get_source_js(pc);
  4166. return result ? result.line : 0;
  4167. },
  4168. // Look up the column number from our stack frame cache with our PC representation.
  4169. emscripten_pc_get_column__deps: ['emscripten_pc_get_source_js'],
  4170. emscripten_pc_get_column: function (pc) {
  4171. var result = _emscripten_pc_get_source_js(pc);
  4172. return result ? result.column || 0 : 0;
  4173. },
  4174. emscripten_get_module_name: function(buf, length) {
  4175. #if MINIMAL_RUNTIME
  4176. return stringToUTF8('{{{ TARGET_BASENAME }}}.wasm', buf, length);
  4177. #else
  4178. return stringToUTF8(wasmBinaryFile, buf, length);
  4179. #endif
  4180. },
  4181. emscripten_with_builtin_malloc__deps: ['emscripten_builtin_malloc', 'emscripten_builtin_free', 'emscripten_builtin_memalign'],
  4182. emscripten_with_builtin_malloc__docs: '/** @suppress{checkTypes} */',
  4183. emscripten_with_builtin_malloc: function (func) {
  4184. var prev_malloc = typeof _malloc !== 'undefined' ? _malloc : undefined;
  4185. var prev_memalign = typeof _memalign !== 'undefined' ? _memalign : undefined;
  4186. var prev_free = typeof _free !== 'undefined' ? _free : undefined;
  4187. _malloc = _emscripten_builtin_malloc;
  4188. _memalign = _emscripten_builtin_memalign;
  4189. _free = _emscripten_builtin_free;
  4190. try {
  4191. return func();
  4192. } finally {
  4193. _malloc = prev_malloc;
  4194. _memalign = prev_memalign;
  4195. _free = prev_free;
  4196. }
  4197. },
  4198. emscripten_builtin_mmap2__deps: ['emscripten_with_builtin_malloc', '$syscallMmap2'],
  4199. emscripten_builtin_mmap2: function (addr, len, prot, flags, fd, off) {
  4200. return _emscripten_with_builtin_malloc(function () {
  4201. return syscallMmap2(addr, len, prot, flags, fd, off);
  4202. });
  4203. },
  4204. emscripten_builtin_munmap__deps: ['emscripten_with_builtin_malloc', '$syscallMunmap'],
  4205. emscripten_builtin_munmap: function (addr, len) {
  4206. return _emscripten_with_builtin_malloc(function () {
  4207. return syscallMunmap(addr, len);
  4208. });
  4209. },
  4210. emscripten_get_stack_top: function() {
  4211. return STACKTOP;
  4212. },
  4213. emscripten_get_stack_base: function() {
  4214. return STACK_BASE;
  4215. },
  4216. $readAsmConstArgs: function(sigPtr, buf) {
  4217. if (!readAsmConstArgs.array) {
  4218. readAsmConstArgs.array = [];
  4219. }
  4220. var args = readAsmConstArgs.array;
  4221. args.length = 0;
  4222. var ch;
  4223. while (ch = HEAPU8[sigPtr++]) {
  4224. if (ch === 100/*'d'*/ || ch === 102/*'f'*/) {
  4225. buf = (buf + 7) & ~7;
  4226. args.push(HEAPF64[(buf >> 3)]);
  4227. buf += 8;
  4228. } else
  4229. #if ASSERTIONS
  4230. if (ch === 105 /*'i'*/)
  4231. #endif
  4232. {
  4233. buf = (buf + 3) & ~3;
  4234. args.push(HEAP32[(buf >> 2)]);
  4235. buf += 4;
  4236. }
  4237. #if ASSERTIONS
  4238. else abort("unexpected char in asm const signature " + ch);
  4239. #endif
  4240. }
  4241. return args;
  4242. },
  4243. #if !DECLARE_ASM_MODULE_EXPORTS
  4244. // When DECLARE_ASM_MODULE_EXPORTS is not set we export native symbols
  4245. // at runtime rather than statically in JS code.
  4246. $exportAsmFunctions: function(asm) {
  4247. #if WASM_BACKEND
  4248. var asmjsMangle = function(x) {
  4249. var unmangledSymbols = {{{ buildStringArray(WASM_FUNCTIONS_THAT_ARE_NOT_NAME_MANGLED) }}};
  4250. return x.indexOf('dynCall_') == 0 || unmangledSymbols.indexOf(x) != -1 ? x : '_' + x;
  4251. };
  4252. #endif
  4253. #if ENVIRONMENT_MAY_BE_NODE
  4254. #if ENVIRONMENT_MAY_BE_WEB
  4255. var global_object = (typeof process !== "undefined" ? global : this);
  4256. #else
  4257. var global_object = global;
  4258. #endif
  4259. #else
  4260. var global_object = this;
  4261. #endif
  4262. for (var __exportedFunc in asm) {
  4263. #if WASM_BACKEND
  4264. var jsname = asmjsMangle(__exportedFunc);
  4265. #else
  4266. var jsname = __exportedFunc;
  4267. #endif
  4268. #if MINIMAL_RUNTIME
  4269. global_object[jsname] = asm[__exportedFunc];
  4270. #else
  4271. global_object[jsname] = Module[jsname] = asm[__exportedFunc];
  4272. #endif
  4273. }
  4274. },
  4275. #endif
  4276. // Parses as much of the given JS string to an integer, with quiet error
  4277. // handling (returns a NaN on error). E.g. jstoi_q("123abc") returns 123.
  4278. // Note that "smart" radix handling is employed for input string:
  4279. // "0314" is parsed as octal, and "0x1234" is parsed as base-16.
  4280. $jstoi_q__docs: '/** @suppress {checkTypes} */',
  4281. $jstoi_q: function(str) {
  4282. return parseInt(str);
  4283. },
  4284. // Converts a JS string to an integer base-10, with signaling error
  4285. // handling (throws a JS exception on error). E.g. jstoi_s("123abc")
  4286. // throws an exception.
  4287. $jstoi_s: function(str) {
  4288. return Number(str);
  4289. },
  4290. //============================
  4291. // i64 math
  4292. //============================
  4293. i64Add__asm: true,
  4294. i64Add__sig: 'iiiii',
  4295. i64Add: function(a, b, c, d) {
  4296. /*
  4297. x = a + b*2^32
  4298. y = c + d*2^32
  4299. result = l + h*2^32
  4300. */
  4301. a = a|0; b = b|0; c = c|0; d = d|0;
  4302. var l = 0, h = 0;
  4303. l = (a + c)>>>0;
  4304. h = (b + d + (((l>>>0) < (a>>>0))|0))>>>0; // Add carry from low word to high word on overflow.
  4305. {{{ makeStructuralReturn(['l|0', 'h'], true) }}};
  4306. },
  4307. i64Subtract__asm: true,
  4308. i64Subtract__sig: 'iiiii',
  4309. i64Subtract: function(a, b, c, d) {
  4310. a = a|0; b = b|0; c = c|0; d = d|0;
  4311. var l = 0, h = 0;
  4312. l = (a - c)>>>0;
  4313. h = (b - d)>>>0;
  4314. h = (b - d - (((c>>>0) > (a>>>0))|0))>>>0; // Borrow one from high word to low word on underflow.
  4315. {{{ makeStructuralReturn(['l|0', 'h'], true) }}};
  4316. },
  4317. bitshift64Shl__asm: true,
  4318. bitshift64Shl__sig: 'iiii',
  4319. bitshift64Shl: function(low, high, bits) {
  4320. low = low|0; high = high|0; bits = bits|0;
  4321. var ander = 0;
  4322. if ((bits|0) < 32) {
  4323. ander = ((1 << bits) - 1)|0;
  4324. {{{ makeSetTempRet0('(high << bits) | ((low&(ander << (32 - bits))) >>> (32 - bits))') }}};
  4325. return low << bits;
  4326. }
  4327. {{{ makeSetTempRet0('low << (bits - 32)') }}};
  4328. return 0;
  4329. },
  4330. bitshift64Ashr__asm: true,
  4331. bitshift64Ashr__sig: 'iiii',
  4332. bitshift64Ashr: function(low, high, bits) {
  4333. low = low|0; high = high|0; bits = bits|0;
  4334. var ander = 0;
  4335. if ((bits|0) < 32) {
  4336. ander = ((1 << bits) - 1)|0;
  4337. {{{ makeSetTempRet0('high >> bits') }}};
  4338. return (low >>> bits) | ((high&ander) << (32 - bits));
  4339. }
  4340. {{{ makeSetTempRet0('(high|0) < 0 ? -1 : 0') }}};
  4341. return (high >> (bits - 32))|0;
  4342. },
  4343. bitshift64Lshr__asm: true,
  4344. bitshift64Lshr__sig: 'iiii',
  4345. bitshift64Lshr: function(low, high, bits) {
  4346. low = low|0; high = high|0; bits = bits|0;
  4347. var ander = 0;
  4348. if ((bits|0) < 32) {
  4349. ander = ((1 << bits) - 1)|0;
  4350. {{{ makeSetTempRet0('high >>> bits') }}};
  4351. return (low >>> bits) | ((high&ander) << (32 - bits));
  4352. }
  4353. {{{ makeSetTempRet0('0') }}};
  4354. return (high >>> (bits - 32))|0;
  4355. },
  4356. // libunwind
  4357. _Unwind_Backtrace__deps: ['emscripten_get_callstack_js'],
  4358. _Unwind_Backtrace: function(func, arg) {
  4359. var trace = _emscripten_get_callstack_js();
  4360. var parts = trace.split('\n');
  4361. for (var i = 0; i < parts.length; i++) {
  4362. var ret = {{{ makeDynCall('iii') }}}(func, 0, arg);
  4363. if (ret !== 0) return;
  4364. }
  4365. },
  4366. _Unwind_GetIPInfo: function() {
  4367. abort('Unwind_GetIPInfo');
  4368. },
  4369. _Unwind_FindEnclosingFunction: function() {
  4370. return 0; // we cannot succeed
  4371. },
  4372. _Unwind_RaiseException__deps: ['__cxa_throw'],
  4373. _Unwind_RaiseException: function(ex) {
  4374. err('Warning: _Unwind_RaiseException is not correctly implemented');
  4375. return ___cxa_throw(ex, 0, 0);
  4376. },
  4377. _Unwind_DeleteException: function(ex) {
  4378. err('TODO: Unwind_DeleteException');
  4379. },
  4380. // autodebugging
  4381. emscripten_autodebug_i64: function(line, valuel, valueh) {
  4382. out('AD:' + [line, valuel, valueh]);
  4383. },
  4384. emscripten_autodebug_i32: function(line, value) {
  4385. out('AD:' + [line, value]);
  4386. },
  4387. emscripten_autodebug_i16: function(line, value) {
  4388. out('AD:' + [line, value]);
  4389. },
  4390. emscripten_autodebug_i8: function(line, value) {
  4391. out('AD:' + [line, value]);
  4392. },
  4393. emscripten_autodebug_float: function(line, value) {
  4394. out('AD:' + [line, value]);
  4395. },
  4396. emscripten_autodebug_double: function(line, value) {
  4397. out('AD:' + [line, value]);
  4398. },
  4399. // special runtime support
  4400. #if MINIMAL_RUNTIME && !WASM_BACKEND
  4401. emscripten_scan_stack__deps: ['$stackSave'],
  4402. #endif
  4403. emscripten_scan_stack: function(func) {
  4404. var base = STACK_BASE; // TODO verify this is right on pthreads
  4405. var end = stackSave();
  4406. {{{ makeDynCall('vii') }}}(func, Math.min(base, end), Math.max(base, end));
  4407. },
  4408. // misc definitions to avoid unnecessary unresolved symbols being reported
  4409. // by fastcomp or wasm-ld
  4410. #if SUPPORT_LONGJMP
  4411. emscripten_prep_setjmp: function() {},
  4412. emscripten_cleanup_setjmp: function() {},
  4413. emscripten_check_longjmp: function() {},
  4414. emscripten_get_longjmp_result: function() {},
  4415. emscripten_setjmp: function() {},
  4416. #endif
  4417. emscripten_preinvoke: function() {},
  4418. emscripten_postinvoke: function() {},
  4419. emscripten_resume: function() {},
  4420. emscripten_landingpad: function() {},
  4421. getHigh32: function() {},
  4422. setHigh32: function() {},
  4423. FtoILow: function() {},
  4424. FtoIHigh: function() {},
  4425. DtoILow: function() {},
  4426. DtoIHigh: function() {},
  4427. BDtoILow: function() {},
  4428. BDtoIHigh: function() {},
  4429. SItoF: function() {},
  4430. UItoF: function() {},
  4431. SItoD: function() {},
  4432. UItoD: function() {},
  4433. BItoD: function() {},
  4434. llvm_dbg_value: function() {},
  4435. llvm_debugtrap: function() {},
  4436. llvm_ctlz_i32: function() {},
  4437. emscripten_asm_const: function() {},
  4438. emscripten_asm_const_int: function() {},
  4439. emscripten_asm_const_double: function() {},
  4440. emscripten_asm_const_int_sync_on_main_thread: function() {},
  4441. emscripten_asm_const_double_sync_on_main_thread: function() {},
  4442. emscripten_asm_const_async_on_main_thread: function() {},
  4443. #if !WASM_BACKEND
  4444. // ======== compiled code from system/lib/compiler-rt , see readme therein
  4445. __muldsi3__asm: true,
  4446. __muldsi3__sig: 'iii',
  4447. __muldsi3__deps: ['Math_imul'],
  4448. __muldsi3: function($a, $b) {
  4449. $a = $a | 0;
  4450. $b = $b | 0;
  4451. var $1 = 0, $2 = 0, $3 = 0, $6 = 0, $8 = 0, $11 = 0, $12 = 0;
  4452. $1 = $a & 65535;
  4453. $2 = $b & 65535;
  4454. $3 = Math_imul($2, $1) | 0;
  4455. $6 = $a >>> 16;
  4456. $8 = ($3 >>> 16) + (Math_imul($2, $6) | 0) | 0;
  4457. $11 = $b >>> 16;
  4458. $12 = Math_imul($11, $1) | 0;
  4459. return ({{{ makeSetTempRet0('(($8 >>> 16) + (Math_imul($11, $6) | 0) | 0) + ((($8 & 65535) + $12 | 0) >>> 16) | 0') }}}, 0 | ($8 + $12 << 16 | $3 & 65535)) | 0;
  4460. },
  4461. __divdi3__sig: 'iiiii',
  4462. __divdi3__asm: true,
  4463. __divdi3__deps: ['__udivmoddi4', 'i64Subtract'],
  4464. __divdi3: function($a$0, $a$1, $b$0, $b$1) {
  4465. $a$0 = $a$0 | 0;
  4466. $a$1 = $a$1 | 0;
  4467. $b$0 = $b$0 | 0;
  4468. $b$1 = $b$1 | 0;
  4469. var $1$0 = 0, $1$1 = 0, $2$0 = 0, $2$1 = 0, $4$0 = 0, $4$1 = 0, $6$0 = 0, $7$0 = 0, $7$1 = 0, $8$0 = 0, $10$0 = 0;
  4470. $1$0 = $a$1 >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1;
  4471. $1$1 = (($a$1 | 0) < 0 ? -1 : 0) >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1;
  4472. $2$0 = $b$1 >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1;
  4473. $2$1 = (($b$1 | 0) < 0 ? -1 : 0) >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1;
  4474. $4$0 = _i64Subtract($1$0 ^ $a$0 | 0, $1$1 ^ $a$1 | 0, $1$0 | 0, $1$1 | 0) | 0;
  4475. $4$1 = {{{ makeGetTempRet0() }}};
  4476. $6$0 = _i64Subtract($2$0 ^ $b$0 | 0, $2$1 ^ $b$1 | 0, $2$0 | 0, $2$1 | 0) | 0;
  4477. $7$0 = $2$0 ^ $1$0;
  4478. $7$1 = $2$1 ^ $1$1;
  4479. $8$0 = ___udivmoddi4($4$0, $4$1, $6$0, {{{ makeGetTempRet0() }}}, 0) | 0;
  4480. $10$0 = _i64Subtract($8$0 ^ $7$0 | 0, {{{ makeGetTempRet0() }}} ^ $7$1 | 0, $7$0 | 0, $7$1 | 0) | 0;
  4481. return $10$0 | 0;
  4482. },
  4483. __remdi3__sig: 'iiiii',
  4484. __remdi3__asm: true,
  4485. __remdi3__deps: ['__udivmoddi4', 'i64Subtract'],
  4486. __remdi3: function($a$0, $a$1, $b$0, $b$1) {
  4487. $a$0 = $a$0 | 0;
  4488. $a$1 = $a$1 | 0;
  4489. $b$0 = $b$0 | 0;
  4490. $b$1 = $b$1 | 0;
  4491. var $rem = 0, $1$0 = 0, $1$1 = 0, $2$0 = 0, $2$1 = 0, $4$0 = 0, $4$1 = 0, $6$0 = 0, $10$0 = 0, $10$1 = 0, __stackBase__ = 0;
  4492. __stackBase__ = STACKTOP;
  4493. STACKTOP = STACKTOP + 16 | 0;
  4494. $rem = __stackBase__ | 0;
  4495. $1$0 = $a$1 >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1;
  4496. $1$1 = (($a$1 | 0) < 0 ? -1 : 0) >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1;
  4497. $2$0 = $b$1 >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1;
  4498. $2$1 = (($b$1 | 0) < 0 ? -1 : 0) >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1;
  4499. $4$0 = _i64Subtract($1$0 ^ $a$0 | 0, $1$1 ^ $a$1 | 0, $1$0 | 0, $1$1 | 0) | 0;
  4500. $4$1 = {{{ makeGetTempRet0() }}};
  4501. $6$0 = _i64Subtract($2$0 ^ $b$0 | 0, $2$1 ^ $b$1 | 0, $2$0 | 0, $2$1 | 0) | 0;
  4502. ___udivmoddi4($4$0, $4$1, $6$0, {{{ makeGetTempRet0() }}}, $rem) | 0;
  4503. $10$0 = _i64Subtract(HEAP32[$rem >> 2] ^ $1$0 | 0, HEAP32[$rem + 4 >> 2] ^ $1$1 | 0, $1$0 | 0, $1$1 | 0) | 0;
  4504. $10$1 = {{{ makeGetTempRet0() }}};
  4505. STACKTOP = __stackBase__;
  4506. return ({{{ makeSetTempRet0('$10$1') }}}, $10$0) | 0;
  4507. },
  4508. __muldi3__sig: 'iiiii',
  4509. __muldi3__asm: true,
  4510. __muldi3__deps: ['__muldsi3', 'Math_imul'],
  4511. __muldi3: function($a$0, $a$1, $b$0, $b$1) {
  4512. $a$0 = $a$0 | 0;
  4513. $a$1 = $a$1 | 0;
  4514. $b$0 = $b$0 | 0;
  4515. $b$1 = $b$1 | 0;
  4516. var $x_sroa_0_0_extract_trunc = 0, $y_sroa_0_0_extract_trunc = 0, $1$0 = 0, $1$1 = 0, $2 = 0;
  4517. $x_sroa_0_0_extract_trunc = $a$0;
  4518. $y_sroa_0_0_extract_trunc = $b$0;
  4519. $1$0 = ___muldsi3($x_sroa_0_0_extract_trunc, $y_sroa_0_0_extract_trunc) | 0;
  4520. $1$1 = {{{ makeGetTempRet0() }}};
  4521. $2 = Math_imul($a$1, $y_sroa_0_0_extract_trunc) | 0;
  4522. return ({{{ makeSetTempRet0('((Math_imul($b$1, $x_sroa_0_0_extract_trunc) | 0) + $2 | 0) + $1$1 | $1$1 & 0') }}}, 0 | $1$0 & -1) | 0;
  4523. },
  4524. __udivdi3__sig: 'iiiii',
  4525. __udivdi3__asm: true,
  4526. __udivdi3__deps: ['__udivmoddi4'],
  4527. __udivdi3: function($a$0, $a$1, $b$0, $b$1) {
  4528. $a$0 = $a$0 | 0;
  4529. $a$1 = $a$1 | 0;
  4530. $b$0 = $b$0 | 0;
  4531. $b$1 = $b$1 | 0;
  4532. var $1$0 = 0;
  4533. $1$0 = ___udivmoddi4($a$0, $a$1, $b$0, $b$1, 0) | 0;
  4534. return $1$0 | 0;
  4535. },
  4536. __uremdi3__sig: 'iiiii',
  4537. __uremdi3__asm: true,
  4538. __uremdi3__deps: ['__udivmoddi4'],
  4539. __uremdi3: function($a$0, $a$1, $b$0, $b$1) {
  4540. $a$0 = $a$0 | 0;
  4541. $a$1 = $a$1 | 0;
  4542. $b$0 = $b$0 | 0;
  4543. $b$1 = $b$1 | 0;
  4544. var $rem = 0, __stackBase__ = 0;
  4545. __stackBase__ = STACKTOP;
  4546. STACKTOP = STACKTOP + 16 | 0;
  4547. $rem = __stackBase__ | 0;
  4548. ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem) | 0;
  4549. STACKTOP = __stackBase__;
  4550. return ({{{ makeSetTempRet0('HEAP32[$rem + 4 >> 2] | 0') }}}, HEAP32[$rem >> 2] | 0) | 0;
  4551. },
  4552. __udivmoddi4__sig: 'iiiiii',
  4553. __udivmoddi4__asm: true,
  4554. __udivmoddi4__deps: ['i64Add', 'i64Subtract', 'llvm_cttz_i32', 'Math_clz32'],
  4555. __udivmoddi4: function($a$0, $a$1, $b$0, $b$1, $rem) {
  4556. $a$0 = $a$0 | 0;
  4557. $a$1 = $a$1 | 0;
  4558. $b$0 = $b$0 | 0;
  4559. $b$1 = $b$1 | 0;
  4560. $rem = $rem | 0;
  4561. var $n_sroa_0_0_extract_trunc = 0, $n_sroa_1_4_extract_shift$0 = 0, $n_sroa_1_4_extract_trunc = 0, $d_sroa_0_0_extract_trunc = 0, $d_sroa_1_4_extract_shift$0 = 0, $d_sroa_1_4_extract_trunc = 0, $4 = 0, $17 = 0, $37 = 0, $49 = 0, $51 = 0, $57 = 0, $58 = 0, $66 = 0, $78 = 0, $86 = 0, $88 = 0, $89 = 0, $91 = 0, $92 = 0, $95 = 0, $105 = 0, $117 = 0, $119 = 0, $125 = 0, $126 = 0, $130 = 0, $q_sroa_1_1_ph = 0, $q_sroa_0_1_ph = 0, $r_sroa_1_1_ph = 0, $r_sroa_0_1_ph = 0, $sr_1_ph = 0, $d_sroa_0_0_insert_insert99$0 = 0, $d_sroa_0_0_insert_insert99$1 = 0, $137$0 = 0, $137$1 = 0, $carry_0203 = 0, $sr_1202 = 0, $r_sroa_0_1201 = 0, $r_sroa_1_1200 = 0, $q_sroa_0_1199 = 0, $q_sroa_1_1198 = 0, $147 = 0, $149 = 0, $r_sroa_0_0_insert_insert42$0 = 0, $r_sroa_0_0_insert_insert42$1 = 0, $150$1 = 0, $151$0 = 0, $152 = 0, $154$0 = 0, $r_sroa_0_0_extract_trunc = 0, $r_sroa_1_4_extract_trunc = 0, $155 = 0, $carry_0_lcssa$0 = 0, $carry_0_lcssa$1 = 0, $r_sroa_0_1_lcssa = 0, $r_sroa_1_1_lcssa = 0, $q_sroa_0_1_lcssa = 0, $q_sroa_1_1_lcssa = 0, $q_sroa_0_0_insert_ext75$0 = 0, $q_sroa_0_0_insert_ext75$1 = 0, $q_sroa_0_0_insert_insert77$1 = 0, $_0$0 = 0, $_0$1 = 0;
  4562. $n_sroa_0_0_extract_trunc = $a$0;
  4563. $n_sroa_1_4_extract_shift$0 = $a$1;
  4564. $n_sroa_1_4_extract_trunc = $n_sroa_1_4_extract_shift$0;
  4565. $d_sroa_0_0_extract_trunc = $b$0;
  4566. $d_sroa_1_4_extract_shift$0 = $b$1;
  4567. $d_sroa_1_4_extract_trunc = $d_sroa_1_4_extract_shift$0;
  4568. if (($n_sroa_1_4_extract_trunc | 0) == 0) {
  4569. $4 = ($rem | 0) != 0;
  4570. if (($d_sroa_1_4_extract_trunc | 0) == 0) {
  4571. if ($4) {
  4572. HEAP32[$rem >> 2] = ($n_sroa_0_0_extract_trunc >>> 0) % ($d_sroa_0_0_extract_trunc >>> 0);
  4573. HEAP32[$rem + 4 >> 2] = 0;
  4574. }
  4575. $_0$1 = 0;
  4576. $_0$0 = ($n_sroa_0_0_extract_trunc >>> 0) / ($d_sroa_0_0_extract_trunc >>> 0) >>> 0;
  4577. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4578. } else {
  4579. if (!$4) {
  4580. $_0$1 = 0;
  4581. $_0$0 = 0;
  4582. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4583. }
  4584. HEAP32[$rem >> 2] = $a$0 & -1;
  4585. HEAP32[$rem + 4 >> 2] = $a$1 & 0;
  4586. $_0$1 = 0;
  4587. $_0$0 = 0;
  4588. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4589. }
  4590. }
  4591. $17 = ($d_sroa_1_4_extract_trunc | 0) == 0;
  4592. do {
  4593. if (($d_sroa_0_0_extract_trunc | 0) == 0) {
  4594. if ($17) {
  4595. if (($rem | 0) != 0) {
  4596. HEAP32[$rem >> 2] = ($n_sroa_1_4_extract_trunc >>> 0) % ($d_sroa_0_0_extract_trunc >>> 0);
  4597. HEAP32[$rem + 4 >> 2] = 0;
  4598. }
  4599. $_0$1 = 0;
  4600. $_0$0 = ($n_sroa_1_4_extract_trunc >>> 0) / ($d_sroa_0_0_extract_trunc >>> 0) >>> 0;
  4601. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4602. }
  4603. if (($n_sroa_0_0_extract_trunc | 0) == 0) {
  4604. if (($rem | 0) != 0) {
  4605. HEAP32[$rem >> 2] = 0;
  4606. HEAP32[$rem + 4 >> 2] = ($n_sroa_1_4_extract_trunc >>> 0) % ($d_sroa_1_4_extract_trunc >>> 0);
  4607. }
  4608. $_0$1 = 0;
  4609. $_0$0 = ($n_sroa_1_4_extract_trunc >>> 0) / ($d_sroa_1_4_extract_trunc >>> 0) >>> 0;
  4610. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4611. }
  4612. $37 = $d_sroa_1_4_extract_trunc - 1 | 0;
  4613. if (($37 & $d_sroa_1_4_extract_trunc | 0) == 0) {
  4614. if (($rem | 0) != 0) {
  4615. HEAP32[$rem >> 2] = 0 | $a$0 & -1;
  4616. HEAP32[$rem + 4 >> 2] = $37 & $n_sroa_1_4_extract_trunc | $a$1 & 0;
  4617. }
  4618. $_0$1 = 0;
  4619. $_0$0 = $n_sroa_1_4_extract_trunc >>> ((_llvm_cttz_i32($d_sroa_1_4_extract_trunc | 0) | 0) >>> 0);
  4620. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4621. }
  4622. $49 = Math_clz32($d_sroa_1_4_extract_trunc | 0) | 0;
  4623. $51 = $49 - (Math_clz32($n_sroa_1_4_extract_trunc | 0) | 0) | 0;
  4624. if ($51 >>> 0 <= 30) {
  4625. $57 = $51 + 1 | 0;
  4626. $58 = 31 - $51 | 0;
  4627. $sr_1_ph = $57;
  4628. $r_sroa_0_1_ph = $n_sroa_1_4_extract_trunc << $58 | $n_sroa_0_0_extract_trunc >>> ($57 >>> 0);
  4629. $r_sroa_1_1_ph = $n_sroa_1_4_extract_trunc >>> ($57 >>> 0);
  4630. $q_sroa_0_1_ph = 0;
  4631. $q_sroa_1_1_ph = $n_sroa_0_0_extract_trunc << $58;
  4632. break;
  4633. }
  4634. if (($rem | 0) == 0) {
  4635. $_0$1 = 0;
  4636. $_0$0 = 0;
  4637. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4638. }
  4639. HEAP32[$rem >> 2] = 0 | $a$0 & -1;
  4640. HEAP32[$rem + 4 >> 2] = $n_sroa_1_4_extract_shift$0 | $a$1 & 0;
  4641. $_0$1 = 0;
  4642. $_0$0 = 0;
  4643. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4644. } else {
  4645. if (!$17) {
  4646. $117 = Math_clz32($d_sroa_1_4_extract_trunc | 0) | 0;
  4647. $119 = $117 - (Math_clz32($n_sroa_1_4_extract_trunc | 0) | 0) | 0;
  4648. if ($119 >>> 0 <= 31) {
  4649. $125 = $119 + 1 | 0;
  4650. $126 = 31 - $119 | 0;
  4651. $130 = $119 - 31 >> 31;
  4652. $sr_1_ph = $125;
  4653. $r_sroa_0_1_ph = $n_sroa_0_0_extract_trunc >>> ($125 >>> 0) & $130 | $n_sroa_1_4_extract_trunc << $126;
  4654. $r_sroa_1_1_ph = $n_sroa_1_4_extract_trunc >>> ($125 >>> 0) & $130;
  4655. $q_sroa_0_1_ph = 0;
  4656. $q_sroa_1_1_ph = $n_sroa_0_0_extract_trunc << $126;
  4657. break;
  4658. }
  4659. if (($rem | 0) == 0) {
  4660. $_0$1 = 0;
  4661. $_0$0 = 0;
  4662. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4663. }
  4664. HEAP32[$rem >> 2] = 0 | $a$0 & -1;
  4665. HEAP32[$rem + 4 >> 2] = $n_sroa_1_4_extract_shift$0 | $a$1 & 0;
  4666. $_0$1 = 0;
  4667. $_0$0 = 0;
  4668. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4669. }
  4670. $66 = $d_sroa_0_0_extract_trunc - 1 | 0;
  4671. if (($66 & $d_sroa_0_0_extract_trunc | 0) != 0) {
  4672. $86 = (Math_clz32($d_sroa_0_0_extract_trunc | 0) | 0) + 33 | 0;
  4673. $88 = $86 - (Math_clz32($n_sroa_1_4_extract_trunc | 0) | 0) | 0;
  4674. $89 = 64 - $88 | 0;
  4675. $91 = 32 - $88 | 0;
  4676. $92 = $91 >> 31;
  4677. $95 = $88 - 32 | 0;
  4678. $105 = $95 >> 31;
  4679. $sr_1_ph = $88;
  4680. $r_sroa_0_1_ph = $91 - 1 >> 31 & $n_sroa_1_4_extract_trunc >>> ($95 >>> 0) | ($n_sroa_1_4_extract_trunc << $91 | $n_sroa_0_0_extract_trunc >>> ($88 >>> 0)) & $105;
  4681. $r_sroa_1_1_ph = $105 & $n_sroa_1_4_extract_trunc >>> ($88 >>> 0);
  4682. $q_sroa_0_1_ph = $n_sroa_0_0_extract_trunc << $89 & $92;
  4683. $q_sroa_1_1_ph = ($n_sroa_1_4_extract_trunc << $89 | $n_sroa_0_0_extract_trunc >>> ($95 >>> 0)) & $92 | $n_sroa_0_0_extract_trunc << $91 & $88 - 33 >> 31;
  4684. break;
  4685. }
  4686. if (($rem | 0) != 0) {
  4687. HEAP32[$rem >> 2] = $66 & $n_sroa_0_0_extract_trunc;
  4688. HEAP32[$rem + 4 >> 2] = 0;
  4689. }
  4690. if (($d_sroa_0_0_extract_trunc | 0) == 1) {
  4691. $_0$1 = $n_sroa_1_4_extract_shift$0 | $a$1 & 0;
  4692. $_0$0 = 0 | $a$0 & -1;
  4693. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4694. } else {
  4695. $78 = _llvm_cttz_i32($d_sroa_0_0_extract_trunc | 0) | 0;
  4696. $_0$1 = 0 | $n_sroa_1_4_extract_trunc >>> ($78 >>> 0);
  4697. $_0$0 = $n_sroa_1_4_extract_trunc << 32 - $78 | $n_sroa_0_0_extract_trunc >>> ($78 >>> 0) | 0;
  4698. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4699. }
  4700. }
  4701. } while (0);
  4702. if (($sr_1_ph | 0) == 0) {
  4703. $q_sroa_1_1_lcssa = $q_sroa_1_1_ph;
  4704. $q_sroa_0_1_lcssa = $q_sroa_0_1_ph;
  4705. $r_sroa_1_1_lcssa = $r_sroa_1_1_ph;
  4706. $r_sroa_0_1_lcssa = $r_sroa_0_1_ph;
  4707. $carry_0_lcssa$1 = 0;
  4708. $carry_0_lcssa$0 = 0;
  4709. } else {
  4710. $d_sroa_0_0_insert_insert99$0 = 0 | $b$0 & -1;
  4711. $d_sroa_0_0_insert_insert99$1 = $d_sroa_1_4_extract_shift$0 | $b$1 & 0;
  4712. $137$0 = _i64Add($d_sroa_0_0_insert_insert99$0 | 0, $d_sroa_0_0_insert_insert99$1 | 0, -1, -1) | 0;
  4713. $137$1 = {{{ makeGetTempRet0() }}};
  4714. $q_sroa_1_1198 = $q_sroa_1_1_ph;
  4715. $q_sroa_0_1199 = $q_sroa_0_1_ph;
  4716. $r_sroa_1_1200 = $r_sroa_1_1_ph;
  4717. $r_sroa_0_1201 = $r_sroa_0_1_ph;
  4718. $sr_1202 = $sr_1_ph;
  4719. $carry_0203 = 0;
  4720. while (1) {
  4721. $147 = $q_sroa_0_1199 >>> 31 | $q_sroa_1_1198 << 1;
  4722. $149 = $carry_0203 | $q_sroa_0_1199 << 1;
  4723. $r_sroa_0_0_insert_insert42$0 = 0 | ($r_sroa_0_1201 << 1 | $q_sroa_1_1198 >>> 31);
  4724. $r_sroa_0_0_insert_insert42$1 = $r_sroa_0_1201 >>> 31 | $r_sroa_1_1200 << 1 | 0;
  4725. _i64Subtract($137$0 | 0, $137$1 | 0, $r_sroa_0_0_insert_insert42$0 | 0, $r_sroa_0_0_insert_insert42$1 | 0) | 0;
  4726. $150$1 = {{{ makeGetTempRet0() }}};
  4727. $151$0 = $150$1 >> 31 | (($150$1 | 0) < 0 ? -1 : 0) << 1;
  4728. $152 = $151$0 & 1;
  4729. $154$0 = _i64Subtract($r_sroa_0_0_insert_insert42$0 | 0, $r_sroa_0_0_insert_insert42$1 | 0, $151$0 & $d_sroa_0_0_insert_insert99$0 | 0, ((($150$1 | 0) < 0 ? -1 : 0) >> 31 | (($150$1 | 0) < 0 ? -1 : 0) << 1) & $d_sroa_0_0_insert_insert99$1 | 0) | 0;
  4730. $r_sroa_0_0_extract_trunc = $154$0;
  4731. $r_sroa_1_4_extract_trunc = {{{ makeGetTempRet0() }}};
  4732. $155 = $sr_1202 - 1 | 0;
  4733. if (($155 | 0) == 0) {
  4734. break;
  4735. } else {
  4736. $q_sroa_1_1198 = $147;
  4737. $q_sroa_0_1199 = $149;
  4738. $r_sroa_1_1200 = $r_sroa_1_4_extract_trunc;
  4739. $r_sroa_0_1201 = $r_sroa_0_0_extract_trunc;
  4740. $sr_1202 = $155;
  4741. $carry_0203 = $152;
  4742. }
  4743. }
  4744. $q_sroa_1_1_lcssa = $147;
  4745. $q_sroa_0_1_lcssa = $149;
  4746. $r_sroa_1_1_lcssa = $r_sroa_1_4_extract_trunc;
  4747. $r_sroa_0_1_lcssa = $r_sroa_0_0_extract_trunc;
  4748. $carry_0_lcssa$1 = 0;
  4749. $carry_0_lcssa$0 = $152;
  4750. }
  4751. $q_sroa_0_0_insert_ext75$0 = $q_sroa_0_1_lcssa;
  4752. $q_sroa_0_0_insert_ext75$1 = 0;
  4753. $q_sroa_0_0_insert_insert77$1 = $q_sroa_1_1_lcssa | $q_sroa_0_0_insert_ext75$1;
  4754. if (($rem | 0) != 0) {
  4755. HEAP32[$rem >> 2] = 0 | $r_sroa_0_1_lcssa;
  4756. HEAP32[$rem + 4 >> 2] = $r_sroa_1_1_lcssa | 0;
  4757. }
  4758. $_0$1 = (0 | $q_sroa_0_0_insert_ext75$0) >>> 31 | $q_sroa_0_0_insert_insert77$1 << 1 | ($q_sroa_0_0_insert_ext75$1 << 1 | $q_sroa_0_0_insert_ext75$0 >>> 31) & 0 | $carry_0_lcssa$1;
  4759. $_0$0 = ($q_sroa_0_0_insert_ext75$0 << 1 | 0 >>> 31) & -2 | $carry_0_lcssa$0;
  4760. return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0;
  4761. },
  4762. // =======================================================================
  4763. #endif
  4764. __handle_stack_overflow: function() {
  4765. abort('stack overflow')
  4766. },
  4767. _getExecutableName: function() {
  4768. #if MINIMAL_RUNTIME // MINIMAL_RUNTIME does not have a global runtime variable thisProgram
  4769. #if ENVIRONMENT_MAY_BE_NODE
  4770. if (ENVIRONMENT_IS_NODE && process['argv'].length > 1) {
  4771. return process['argv'][1].replace(/\\/g, '/');
  4772. }
  4773. #endif
  4774. return "./this.program";
  4775. #else
  4776. return thisProgram || './this.program';
  4777. #endif
  4778. },
  4779. };
  4780. function autoAddDeps(object, name) {
  4781. for (var item in object) {
  4782. if (item.substr(-6) != '__deps') {
  4783. if (!object[item + '__deps']) {
  4784. object[item + '__deps'] = [name];
  4785. } else {
  4786. object[item + '__deps'].push(name); // add to existing list
  4787. }
  4788. }
  4789. }
  4790. }