]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/duktape-1.3.0/examples/cmdline/duk_cmdline_ajduk.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.3.0 / examples / cmdline / duk_cmdline_ajduk.c
1 /*
2 * 'ajduk' specific functionality, examples for low memory techniques
3 */
4
5 #ifdef DUK_CMDLINE_AJSHEAP
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <time.h>
11 #include "ajs.h"
12 #include "ajs_heap.h"
13
14 extern uint8_t dbgHEAPDUMP;
15
16 /*
17 * Helpers
18 */
19
20 static void safe_print_chars(const char *p, duk_size_t len, int until_nul) {
21 duk_size_t i;
22
23 printf("\"");
24 for (i = 0; i < len; i++) {
25 unsigned char x = (unsigned char) p[i];
26 if (until_nul && x == 0U) {
27 break;
28 }
29 if (x < 0x20 || x >= 0x7e || x == '"' || x == '\'' || x == '\\') {
30 printf("\\x%02x", (int) x);
31 } else {
32 printf("%c", (char) x);
33 }
34 }
35 printf("\"");
36 }
37
38 /*
39 * Heap initialization when using AllJoyn.js pool allocator (without any
40 * other AllJoyn.js integration). This serves as an example of how to
41 * integrate Duktape with a pool allocator and is useful for low memory
42 * testing.
43 *
44 * The pool sizes are not optimized here. The sizes are chosen so that
45 * you can look at the high water mark (hwm) and use counts (use) and see
46 * how much allocations are needed for each pool size. To optimize pool
47 * sizes more accurately, you can use --alloc-logging and inspect the memory
48 * allocation log which provides exact byte counts etc.
49 *
50 * https://git.allseenalliance.org/cgit/core/alljoyn-js.git
51 * https://git.allseenalliance.org/cgit/core/alljoyn-js.git/tree/ajs.c
52 */
53
54 static const AJS_HeapConfig ajsheap_config[] = {
55 { 8, 10, AJS_POOL_BORROW, 0 },
56 { 12, 10, AJS_POOL_BORROW, 0 },
57 { 16, 200, AJS_POOL_BORROW, 0 },
58 { 20, 400, AJS_POOL_BORROW, 0 },
59 { 24, 400, AJS_POOL_BORROW, 0 },
60 { 28, 200, AJS_POOL_BORROW, 0 },
61 { 32, 200, AJS_POOL_BORROW, 0 },
62 { 40, 200, AJS_POOL_BORROW, 0 },
63 { 48, 50, AJS_POOL_BORROW, 0 },
64 { 52, 50, AJS_POOL_BORROW, 0 },
65 { 56, 50, AJS_POOL_BORROW, 0 },
66 { 60, 50, AJS_POOL_BORROW, 0 },
67 { 64, 50, AJS_POOL_BORROW, 0 },
68 { 128, 80, AJS_POOL_BORROW, 0 },
69 { 256, 16, AJS_POOL_BORROW, 0 },
70 { 512, 16, AJS_POOL_BORROW, 0 },
71 { 1024, 6, AJS_POOL_BORROW, 0 },
72 { 1360, 1, AJS_POOL_BORROW, 0 }, /* duk_heap, with heap ptr compression */
73 { 2048, 5, AJS_POOL_BORROW, 0 },
74 { 4096, 3, 0, 0 },
75 { 8192, 3, 0, 0 },
76 { 16384, 1, 0, 0 },
77 { 32768, 1, 0, 0 }
78 };
79
80 uint8_t *ajsheap_ram = NULL;
81
82 void ajsheap_init(void) {
83 size_t heap_sz[1];
84 uint8_t *heap_array[1];
85 uint8_t num_pools, i;
86 AJ_Status ret;
87
88 num_pools = (uint8_t) (sizeof(ajsheap_config) / sizeof(AJS_HeapConfig));
89 heap_sz[0] = AJS_HeapRequired(ajsheap_config, /* heapConfig */
90 num_pools, /* numPools */
91 0); /* heapNum */
92 ajsheap_ram = (uint8_t *) malloc(heap_sz[0]);
93 if (ajsheap_ram == NULL) {
94 fprintf(stderr, "Failed to allocate AJS heap\n");
95 fflush(stderr);
96 exit(1);
97 }
98 heap_array[0] = ajsheap_ram;
99
100 fprintf(stderr, "Allocated AJS heap of %ld bytes, pools:", (long) heap_sz[0]);
101 for (i = 0; i < num_pools; i++) {
102 fprintf(stderr, " (sz:%ld,num:%ld,brw:%ld,idx:%ld)",
103 (long) ajsheap_config[i].size, (long) ajsheap_config[i].entries,
104 (long) ajsheap_config[i].borrow, (long) ajsheap_config[i].heapIndex);
105 }
106 fprintf(stderr, "\n");
107 fflush(stderr);
108
109 ret = AJS_HeapInit((void **) heap_array, /* heap */
110 (size_t *) heap_sz, /* heapSz */
111 ajsheap_config, /* heapConfig */
112 num_pools, /* numPools */
113 1); /* numHeaps */
114 fprintf(stderr, "AJS_HeapInit() -> %ld\n", (long) ret);
115 fflush(stderr);
116
117 /* Enable heap dumps */
118 dbgHEAPDUMP = 1;
119 }
120
121 /* AjsHeap.dump(), allows Ecmascript code to dump heap status at suitable
122 * points.
123 */
124 duk_ret_t ajsheap_dump_binding(duk_context *ctx) {
125 AJS_HeapDump();
126 fflush(stdout);
127 return 0;
128 }
129
130 void ajsheap_dump(void) {
131 AJS_HeapDump();
132 fflush(stdout);
133 }
134
135 void ajsheap_register(duk_context *ctx) {
136 duk_push_object(ctx);
137 duk_push_c_function(ctx, ajsheap_dump_binding, 0);
138 duk_put_prop_string(ctx, -2, "dump");
139 duk_put_global_string(ctx, "AjsHeap");
140 }
141
142 /*
143 * Wrapped ajs_heap.c alloc functions
144 *
145 * Used to write an alloc log.
146 */
147
148 static FILE *ajsheap_alloc_log = NULL;
149
150 static void ajsheap_write_alloc_log(const char *fmt, ...) {
151 va_list ap;
152 char buf[256];
153
154 va_start(ap, fmt);
155 vsnprintf(buf, sizeof(buf), fmt, ap);
156 buf[sizeof(buf) - 1] = (char) 0;
157 va_end(ap);
158
159 if (ajsheap_alloc_log == NULL) {
160 ajsheap_alloc_log = fopen("/tmp/ajduk-alloc-log.txt", "wb");
161 if (ajsheap_alloc_log == NULL) {
162 fprintf(stderr, "WARNING: failed to write alloc log, ignoring\n");
163 fflush(stderr);
164 return;
165 }
166 }
167
168 (void) fwrite((const void *) buf, 1, strlen(buf), ajsheap_alloc_log);
169 (void) fflush(ajsheap_alloc_log);
170 }
171
172 void *ajsheap_alloc_wrapped(void *udata, duk_size_t size) {
173 void *ret = AJS_Alloc(udata, size);
174 if (size > 0 && ret == NULL) {
175 ajsheap_write_alloc_log("A FAIL %ld\n", (long) size);
176 } else if (ret == NULL) {
177 ajsheap_write_alloc_log("A NULL %ld\n", (long) size);
178 } else {
179 ajsheap_write_alloc_log("A %p %ld\n", ret, (long) size);
180 }
181 return ret;
182 }
183
184 void *ajsheap_realloc_wrapped(void *udata, void *ptr, duk_size_t size) {
185 void *ret = AJS_Realloc(udata, ptr, size);
186 if (size > 0 && ret == NULL) {
187 if (ptr == NULL) {
188 ajsheap_write_alloc_log("R NULL -1 FAIL %ld\n", (long) size);
189 } else {
190 ajsheap_write_alloc_log("R %p -1 FAIL %ld\n", ptr, (long) size);
191 }
192 } else if (ret == NULL) {
193 if (ptr == NULL) {
194 ajsheap_write_alloc_log("R NULL -1 NULL %ld\n", (long) size);
195 } else {
196 ajsheap_write_alloc_log("R %p -1 NULL %ld\n", ptr, (long) size);
197 }
198 } else {
199 if (ptr == NULL) {
200 ajsheap_write_alloc_log("R NULL -1 %p %ld\n", ret, (long) size);
201 } else {
202 ajsheap_write_alloc_log("R %p -1 %p %ld\n", ptr, ret, (long) size);
203 }
204 }
205 return ret;
206 }
207
208 void ajsheap_free_wrapped(void *udata, void *ptr) {
209 AJS_Free(udata, ptr);
210 if (ptr == NULL) {
211 } else {
212 ajsheap_write_alloc_log("F %p -1\n", ptr);
213 }
214 }
215
216 /*
217 * Example pointer compression functions.
218 *
219 * 'base' is chosen so that no non-NULL pointer results in a zero result
220 * which is reserved for NULL pointers.
221 */
222
223 duk_uint16_t ajsheap_enc16(void *ud, void *p) {
224 duk_uint32_t ret;
225 char *base = (char *) ajsheap_ram - 4;
226
227 /* Userdata is not needed in this case but would be useful if heap
228 * pointer compression were used for multiple heaps. The userdata
229 * allows the callback to distinguish between heaps and their base
230 * pointers.
231 *
232 * If not needed, the userdata can be left out during compilation
233 * by simply ignoring the userdata argument of the pointer encode
234 * and decode macros. It is kept here so that any bugs in actually
235 * providing the value inside Duktape are revealed during compilation.
236 */
237 (void) ud;
238 #if 1
239 /* Ensure that we always get the heap_udata given in heap creation.
240 * (Useful for Duktape development, not needed for user programs.)
241 */
242 if (ud != (void *) 0xdeadbeef) {
243 fprintf(stderr, "invalid udata for ajsheap_enc16: %p\n", ud);
244 fflush(stderr);
245 }
246 #endif
247
248 if (p == NULL) {
249 ret = 0;
250 } else {
251 ret = (duk_uint32_t) (((char *) p - base) >> 2);
252 }
253 #if 0
254 printf("ajsheap_enc16: %p -> %u\n", p, (unsigned int) ret);
255 #endif
256 if (ret > 0xffffUL) {
257 fprintf(stderr, "Failed to compress pointer\n");
258 fflush(stderr);
259 abort();
260 }
261 return (duk_uint16_t) ret;
262 }
263 void *ajsheap_dec16(void *ud, duk_uint16_t x) {
264 void *ret;
265 char *base = (char *) ajsheap_ram - 4;
266
267 /* See userdata discussion in ajsheap_enc16(). */
268 (void) ud;
269 #if 1
270 /* Ensure that we always get the heap_udata given in heap creation. */
271 if (ud != (void *) 0xdeadbeef) {
272 fprintf(stderr, "invalid udata for ajsheap_dec16: %p\n", ud);
273 fflush(stderr);
274 }
275 #endif
276
277 if (x == 0) {
278 ret = NULL;
279 } else {
280 ret = (void *) (base + (((duk_uint32_t) x) << 2));
281 }
282 #if 0
283 printf("ajsheap_dec16: %u -> %p\n", (unsigned int) x, ret);
284 #endif
285 return ret;
286 }
287
288 /*
289 * Simplified example of an external strings strategy where incoming strings
290 * are written sequentially into a fixed, memory mapped flash area.
291 *
292 * The example first scans if the string is already in the flash (which may
293 * happen if the same string is interned multiple times), then adds it to
294 * flash if there is space.
295 *
296 * This example is too slow to be used in a real world application: there
297 * should be e.g. a hash table to quickly check for strings that are already
298 * present in the string data (similarly to how string interning works in
299 * Duktape itself).
300 */
301
302 static uint8_t ajsheap_strdata[65536];
303 static size_t ajsheap_strdata_used = 0;
304
305 const void *ajsheap_extstr_check_1(const void *ptr, duk_size_t len) {
306 uint8_t *p, *p_end;
307 uint8_t initial;
308 uint8_t *ret;
309 size_t left;
310
311 (void) safe_print_chars; /* potentially unused */
312
313 if (len <= 3) {
314 /* It's not worth it to make very small strings external, as
315 * they would take the same space anyway. Also avoids zero
316 * length degenerate case.
317 */
318 return NULL;
319 }
320
321 /*
322 * Check if we already have the string. Be careful to compare for
323 * NUL terminator too, it is NOT present in 'ptr'. This algorithm
324 * is too simplistic and way too slow for actual use.
325 */
326
327 initial = ((const uint8_t *) ptr)[0];
328 for (p = ajsheap_strdata, p_end = p + ajsheap_strdata_used; p != p_end; p++) {
329 if (*p != initial) {
330 continue;
331 }
332 left = (size_t) (p_end - p);
333 if (left >= len + 1 &&
334 memcmp(p, ptr, len) == 0 &&
335 p[len] == 0) {
336 ret = p;
337 #if 0
338 printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ",
339 (void *) ptr, (long) len);
340 safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
341 printf(" -> existing %p (used=%ld)\n",
342 (void *) ret, (long) ajsheap_strdata_used);
343 #endif
344 return ret;
345 }
346 }
347
348 /*
349 * Not present yet, check if we have space. Again, be careful to
350 * ensure there is space for a NUL following the input data.
351 */
352
353 if (ajsheap_strdata_used + len + 1 > sizeof(ajsheap_strdata)) {
354 #if 0
355 printf("ajsheap_extstr_check_1: ptr=%p, len=%ld ", (void *) ptr, (long) len);
356 safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
357 printf(" -> no space (used=%ld)\n", (long) ajsheap_strdata_used);
358 #endif
359 return NULL;
360 }
361
362 /*
363 * There is space, add the string to our collection, being careful
364 * to append the NUL.
365 */
366
367 ret = ajsheap_strdata + ajsheap_strdata_used;
368 memcpy(ret, ptr, len);
369 ret[len] = (uint8_t) 0;
370 ajsheap_strdata_used += len + 1;
371
372 #if 0
373 printf("ajsheap_extstr_check_1: ptr=%p, len=%ld -> ", (void *) ptr, (long) len);
374 safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
375 printf(" -> %p (used=%ld)\n", (void *) ret, (long) ajsheap_strdata_used);
376 #endif
377 return (const void *) ret;
378 }
379
380 void ajsheap_extstr_free_1(const void *ptr) {
381 (void) ptr;
382 #if 0
383 printf("ajsheap_extstr_free_1: freeing extstr %p -> ", ptr);
384 safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/);
385 printf("\n");
386 #endif
387 }
388
389 /*
390 * Simplified example of an external strings strategy where a set of strings
391 * is gathered during application compile time and baked into the application
392 * binary.
393 *
394 * Duktape built-in strings are available from duk_build_meta.json, see
395 * util/duk_meta_to_strarray.py. There may also be a lot of application
396 * specific strings, e.g. those used by application specific APIs. These
397 * must be gathered through some other means, see e.g. util/scan_strings.py.
398 */
399
400 static const char *strdata_duk_builtin_strings[] = {
401 /*
402 * These strings are from util/duk_meta_to_strarray.py
403 */
404
405 "Logger",
406 "Thread",
407 "Pointer",
408 "Buffer",
409 "DecEnv",
410 "ObjEnv",
411 "",
412 "global",
413 "Arguments",
414 "JSON",
415 "Math",
416 "Error",
417 "RegExp",
418 "Date",
419 "Number",
420 "Boolean",
421 "String",
422 "Array",
423 "Function",
424 "Object",
425 "Null",
426 "Undefined",
427 "{_func:true}",
428 "{\x22" "_func\x22" ":true}",
429 "{\x22" "_ninf\x22" ":true}",
430 "{\x22" "_inf\x22" ":true}",
431 "{\x22" "_nan\x22" ":true}",
432 "{\x22" "_undef\x22" ":true}",
433 "toLogString",
434 "clog",
435 "l",
436 "n",
437 "fatal",
438 "error",
439 "warn",
440 "debug",
441 "trace",
442 "raw",
443 "fmt",
444 "current",
445 "resume",
446 "compact",
447 "jc",
448 "jx",
449 "base64",
450 "hex",
451 "dec",
452 "enc",
453 "fin",
454 "gc",
455 "act",
456 "info",
457 "version",
458 "env",
459 "modLoaded",
460 "modSearch",
461 "errThrow",
462 "errCreate",
463 "compile",
464 "\xff" "Regbase",
465 "\xff" "Thread",
466 "\xff" "Handler",
467 "\xff" "Finalizer",
468 "\xff" "Callee",
469 "\xff" "Map",
470 "\xff" "Args",
471 "\xff" "This",
472 "\xff" "Pc2line",
473 "\xff" "Source",
474 "\xff" "Varenv",
475 "\xff" "Lexenv",
476 "\xff" "Varmap",
477 "\xff" "Formals",
478 "\xff" "Bytecode",
479 "\xff" "Next",
480 "\xff" "Target",
481 "\xff" "Value",
482 "pointer",
483 "buffer",
484 "\xff" "Tracedata",
485 "lineNumber",
486 "fileName",
487 "pc",
488 "stack",
489 "ThrowTypeError",
490 "Duktape",
491 "id",
492 "require",
493 "__proto__",
494 "setPrototypeOf",
495 "ownKeys",
496 "enumerate",
497 "deleteProperty",
498 "has",
499 "Proxy",
500 "callee",
501 "Invalid Date",
502 "[...]",
503 "\x0a" "\x09",
504 " ",
505 ",",
506 "-0",
507 "+0",
508 "0",
509 "-Infinity",
510 "+Infinity",
511 "Infinity",
512 "object",
513 "string",
514 "number",
515 "boolean",
516 "undefined",
517 "stringify",
518 "tan",
519 "sqrt",
520 "sin",
521 "round",
522 "random",
523 "pow",
524 "min",
525 "max",
526 "log",
527 "floor",
528 "exp",
529 "cos",
530 "ceil",
531 "atan2",
532 "atan",
533 "asin",
534 "acos",
535 "abs",
536 "SQRT2",
537 "SQRT1_2",
538 "PI",
539 "LOG10E",
540 "LOG2E",
541 "LN2",
542 "LN10",
543 "E",
544 "message",
545 "name",
546 "input",
547 "index",
548 "(?:)",
549 "lastIndex",
550 "multiline",
551 "ignoreCase",
552 "source",
553 "test",
554 "exec",
555 "toGMTString",
556 "setYear",
557 "getYear",
558 "toJSON",
559 "toISOString",
560 "toUTCString",
561 "setUTCFullYear",
562 "setFullYear",
563 "setUTCMonth",
564 "setMonth",
565 "setUTCDate",
566 "setDate",
567 "setUTCHours",
568 "setHours",
569 "setUTCMinutes",
570 "setMinutes",
571 "setUTCSeconds",
572 "setSeconds",
573 "setUTCMilliseconds",
574 "setMilliseconds",
575 "setTime",
576 "getTimezoneOffset",
577 "getUTCMilliseconds",
578 "getMilliseconds",
579 "getUTCSeconds",
580 "getSeconds",
581 "getUTCMinutes",
582 "getMinutes",
583 "getUTCHours",
584 "getHours",
585 "getUTCDay",
586 "getDay",
587 "getUTCDate",
588 "getDate",
589 "getUTCMonth",
590 "getMonth",
591 "getUTCFullYear",
592 "getFullYear",
593 "getTime",
594 "toLocaleTimeString",
595 "toLocaleDateString",
596 "toTimeString",
597 "toDateString",
598 "now",
599 "UTC",
600 "parse",
601 "toPrecision",
602 "toExponential",
603 "toFixed",
604 "POSITIVE_INFINITY",
605 "NEGATIVE_INFINITY",
606 "NaN",
607 "MIN_VALUE",
608 "MAX_VALUE",
609 "substr",
610 "trim",
611 "toLocaleUpperCase",
612 "toUpperCase",
613 "toLocaleLowerCase",
614 "toLowerCase",
615 "substring",
616 "split",
617 "search",
618 "replace",
619 "match",
620 "localeCompare",
621 "charCodeAt",
622 "charAt",
623 "fromCharCode",
624 "reduceRight",
625 "reduce",
626 "filter",
627 "map",
628 "forEach",
629 "some",
630 "every",
631 "lastIndexOf",
632 "indexOf",
633 "unshift",
634 "splice",
635 "sort",
636 "slice",
637 "shift",
638 "reverse",
639 "push",
640 "pop",
641 "join",
642 "concat",
643 "isArray",
644 "arguments",
645 "caller",
646 "bind",
647 "call",
648 "apply",
649 "propertyIsEnumerable",
650 "isPrototypeOf",
651 "hasOwnProperty",
652 "valueOf",
653 "toLocaleString",
654 "toString",
655 "constructor",
656 "set",
657 "get",
658 "enumerable",
659 "configurable",
660 "writable",
661 "value",
662 "keys",
663 "isExtensible",
664 "isFrozen",
665 "isSealed",
666 "preventExtensions",
667 "freeze",
668 "seal",
669 "defineProperties",
670 "defineProperty",
671 "create",
672 "getOwnPropertyNames",
673 "getOwnPropertyDescriptor",
674 "getPrototypeOf",
675 "prototype",
676 "length",
677 "alert",
678 "print",
679 "unescape",
680 "escape",
681 "encodeURIComponent",
682 "encodeURI",
683 "decodeURIComponent",
684 "decodeURI",
685 "isFinite",
686 "isNaN",
687 "parseFloat",
688 "parseInt",
689 "eval",
690 "URIError",
691 "TypeError",
692 "SyntaxError",
693 "ReferenceError",
694 "RangeError",
695 "EvalError",
696 "break",
697 "case",
698 "catch",
699 "continue",
700 "debugger",
701 "default",
702 "delete",
703 "do",
704 "else",
705 "finally",
706 "for",
707 "function",
708 "if",
709 "in",
710 "instanceof",
711 "new",
712 "return",
713 "switch",
714 "this",
715 "throw",
716 "try",
717 "typeof",
718 "var",
719 "void",
720 "while",
721 "with",
722 "class",
723 "const",
724 "enum",
725 "export",
726 "extends",
727 "import",
728 "super",
729 "null",
730 "true",
731 "false",
732 "implements",
733 "interface",
734 "let",
735 "package",
736 "private",
737 "protected",
738 "public",
739 "static",
740 "yield",
741
742 /*
743 * These strings are manually added, and would be gathered in some
744 * application specific manner.
745 */
746
747 "foo",
748 "bar",
749 "quux",
750 "enableFrob",
751 "disableFrob"
752 /* ... */
753 };
754
755 const void *ajsheap_extstr_check_2(const void *ptr, duk_size_t len) {
756 int i, n;
757
758 (void) safe_print_chars; /* potentially unused */
759
760 /* Linear scan. An actual implementation would need some acceleration
761 * structure, e.g. select a sublist based on first character.
762 *
763 * NOTE: input string (behind 'ptr' with 'len' bytes) DOES NOT have a
764 * trailing NUL character. Any strings returned from this function
765 * MUST have a trailing NUL character.
766 */
767
768 n = (int) (sizeof(strdata_duk_builtin_strings) / sizeof(const char *));
769 for (i = 0; i < n; i++) {
770 const char *str;
771
772 str = strdata_duk_builtin_strings[i];
773 if (strlen(str) == len && memcmp(ptr, (const void *) str, len) == 0) {
774 #if 0
775 printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ",
776 (void *) ptr, (long) len);
777 safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
778 printf(" -> constant string index %ld\n", (long) i);
779 #endif
780 return (void *) strdata_duk_builtin_strings[i];
781 }
782 }
783
784 #if 0
785 printf("ajsheap_extstr_check_2: ptr=%p, len=%ld ",
786 (void *) ptr, (long) len);
787 safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
788 printf(" -> not found\n");
789 #endif
790 return NULL;
791 }
792
793 void ajsheap_extstr_free_2(const void *ptr) {
794 (void) ptr;
795 #if 0
796 printf("ajsheap_extstr_free_2: freeing extstr %p -> ", ptr);
797 safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/);
798 printf("\n");
799 #endif
800 }
801
802 /*
803 * External strings strategy intended for valgrind testing: external strings
804 * are allocated using malloc()/free() so that valgrind can be used to ensure
805 * that strings are e.g. freed exactly once.
806 */
807
808 const void *ajsheap_extstr_check_3(const void *ptr, duk_size_t len) {
809 duk_uint8_t *ret;
810
811 (void) safe_print_chars; /* potentially unused */
812
813 ret = malloc((size_t) len + 1);
814 if (ret == NULL) {
815 #if 0
816 printf("ajsheap_extstr_check_3: ptr=%p, len=%ld ",
817 (void *) ptr, (long) len);
818 safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
819 printf(" -> malloc failed, return NULL\n");
820 #endif
821 return (const void *) NULL;
822 }
823
824 if (len > 0) {
825 memcpy((void *) ret, ptr, (size_t) len);
826 }
827 ret[len] = (duk_uint8_t) 0;
828
829 #if 0
830 printf("ajsheap_extstr_check_3: ptr=%p, len=%ld ",
831 (void *) ptr, (long) len);
832 safe_print_chars((const char *) ptr, len, 0 /*until_nul*/);
833 printf(" -> %p\n", (void *) ret);
834 #endif
835 return (const void *) ret;
836 }
837
838 void ajsheap_extstr_free_3(const void *ptr) {
839 (void) ptr;
840 #if 0
841 printf("ajsheap_extstr_free_3: freeing extstr %p -> ", ptr);
842 safe_print_chars((const char *) ptr, DUK_SIZE_MAX, 1 /*until_nul*/);
843 printf("\n");
844 #endif
845 free((void *) ptr);
846 }
847
848 /*
849 * Execution timeout example
850 */
851
852 #define AJSHEAP_EXEC_TIMEOUT 5 /* seconds */
853
854 static time_t curr_pcall_start = 0;
855 static long exec_timeout_check_counter = 0;
856
857 void ajsheap_start_exec_timeout(void) {
858 curr_pcall_start = time(NULL);
859 }
860
861 void ajsheap_clear_exec_timeout(void) {
862 curr_pcall_start = 0;
863 }
864
865 duk_bool_t ajsheap_exec_timeout_check(void *udata) {
866 time_t now = time(NULL);
867 time_t diff = now - curr_pcall_start;
868
869 (void) udata; /* not needed */
870
871 exec_timeout_check_counter++;
872 #if 0
873 printf("exec timeout check %ld: now=%ld, start=%ld, diff=%ld\n",
874 (long) exec_timeout_check_counter, (long) now, (long) curr_pcall_start, (long) diff);
875 fflush(stdout);
876 #endif
877
878 if (curr_pcall_start == 0) {
879 /* protected call not yet running */
880 return 0;
881 }
882 if (diff > AJSHEAP_EXEC_TIMEOUT) {
883 return 1;
884 }
885 return 0;
886 }
887
888 #else /* DUK_CMDLINE_AJSHEAP */
889
890 int ajs_dummy = 0; /* to avoid empty source file */
891
892 #endif /* DUK_CMDLINE_AJSHEAP */