Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/mujs/main.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/mujs/main.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,394 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef _MSC_VER +#include <io.h> +#else +#include <unistd.h> +#endif +#include <errno.h> + +#include "mujs.h" + +static char *xoptarg; /* Global argument pointer. */ +static int xoptind = 0; /* Global argv index. */ +static int xgetopt(int argc, char *argv[], char *optstring) +{ + static char *scan = NULL; /* Private scan pointer. */ + + char c; + char *place; + + xoptarg = NULL; + + if (!scan || *scan == '\0') { + if (xoptind == 0) + xoptind++; + + if (xoptind >= argc || argv[xoptind][0] != '-' || argv[xoptind][1] == '\0') + return EOF; + if (argv[xoptind][1] == '-' && argv[xoptind][2] == '\0') { + xoptind++; + return EOF; + } + + scan = argv[xoptind]+1; + xoptind++; + } + + c = *scan++; + place = strchr(optstring, c); + + if (!place || c == ':') { + fprintf(stderr, "%s: unknown option -%c\n", argv[0], c); + return '?'; + } + + place++; + if (*place == ':') { + if (*scan != '\0') { + xoptarg = scan; + scan = NULL; + } else if (xoptind < argc) { + xoptarg = argv[xoptind]; + xoptind++; + } else { + fprintf(stderr, "%s: option requires argument -%c\n", argv[0], c); + return ':'; + } + } + + return c; +} + +#ifdef HAVE_READLINE +#include <readline/readline.h> +#include <readline/history.h> +#else +void using_history(void) { } +void add_history(const char *string) { } +void rl_bind_key(int key, void (*fun)(void)) { } +void rl_insert(void) { } +char *readline(const char *prompt) +{ + static char line[500], *p; + int n; + fputs(prompt, stdout); + p = fgets(line, sizeof line, stdin); + if (p) { + n = strlen(line); + if (n > 0 && line[n-1] == '\n') + line[--n] = 0; + p = malloc(n+1); + memcpy(p, line, n+1); + return p; + } + return NULL; +} +#endif + +#define PS1 "> " + +static void jsB_gc(js_State *J) +{ + int report = js_toboolean(J, 1); + js_gc(J, report); + js_pushundefined(J); +} + +static void jsB_load(js_State *J) +{ + int i, n = js_gettop(J); + for (i = 1; i < n; ++i) { + js_loadfile(J, js_tostring(J, i)); + js_pushundefined(J); + js_call(J, 0); + js_pop(J, 1); + } + js_pushundefined(J); +} + +static void jsB_compile(js_State *J) +{ + const char *source = js_tostring(J, 1); + const char *filename = js_isdefined(J, 2) ? js_tostring(J, 2) : "[string]"; + js_loadstring(J, filename, source); +} + +static void jsB_print(js_State *J) +{ + int i, top = js_gettop(J); + for (i = 1; i < top; ++i) { + const char *s = js_tostring(J, i); + if (i > 1) putchar(' '); + fputs(s, stdout); + } + putchar('\n'); + js_pushundefined(J); +} + +static void jsB_write(js_State *J) +{ + int i, top = js_gettop(J); + for (i = 1; i < top; ++i) { + const char *s = js_tostring(J, i); + if (i > 1) putchar(' '); + fputs(s, stdout); + } + js_pushundefined(J); +} + +static void jsB_read(js_State *J) +{ + const char *filename = js_tostring(J, 1); + FILE *f; + char *s; + int n, t; + + f = fopen(filename, "rb"); + if (!f) { + js_error(J, "cannot open file '%s': %s", filename, strerror(errno)); + } + + if (fseek(f, 0, SEEK_END) < 0) { + fclose(f); + js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno)); + } + + n = ftell(f); + if (n < 0) { + fclose(f); + js_error(J, "cannot tell in file '%s': %s", filename, strerror(errno)); + } + + if (fseek(f, 0, SEEK_SET) < 0) { + fclose(f); + js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno)); + } + + s = malloc(n + 1); + if (!s) { + fclose(f); + js_error(J, "out of memory"); + } + + t = fread(s, 1, n, f); + if (t != n) { + free(s); + fclose(f); + js_error(J, "cannot read data from file '%s': %s", filename, strerror(errno)); + } + s[n] = 0; + + js_pushstring(J, s); + free(s); + fclose(f); +} + +static void jsB_readline(js_State *J) +{ + char *line = readline(""); + if (!line) { + js_pushnull(J); + return; + } + js_pushstring(J, line); + if (*line) + add_history(line); + free(line); +} + +static void jsB_quit(js_State *J) +{ + exit(js_tonumber(J, 1)); +} + +static void jsB_repr(js_State *J) +{ + js_repr(J, 1); +} + +static const char *require_js = + "function require(name) {\n" + "var cache = require.cache;\n" + "if (name in cache) return cache[name];\n" + "var exports = {};\n" + "cache[name] = exports;\n" + "Function('exports', read(name+'.js'))(exports);\n" + "return exports;\n" + "}\n" + "require.cache = Object.create(null);\n" +; + + +static const char *stacktrace_js = + "Error.prototype.toString = function() {\n" + "var s = this.name;\n" + "if ('message' in this) s += ': ' + this.message;\n" + "if ('stackTrace' in this) s += this.stackTrace;\n" + "return s;\n" + "};\n" +; + +static const char *console_js = + "var console = { log: print, debug: print, warn: print, error: print };" +; + +static int eval_print(js_State *J, const char *source) +{ + if (js_ploadstring(J, "[stdin]", source)) { + fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); + js_pop(J, 1); + return 1; + } + js_pushundefined(J); + if (js_pcall(J, 0)) { + fprintf(stderr, "%s\n", js_trystring(J, -1, "Error")); + js_pop(J, 1); + return 1; + } + if (js_isdefined(J, -1)) { + printf("%s\n", js_tryrepr(J, -1, "can't convert to string")); + } + js_pop(J, 1); + return 0; +} + +static char *read_stdin(void) +{ + int n = 0; + int t = 512; + char *s = NULL; + + for (;;) { + char *ss = realloc(s, t); + if (!ss) { + free(s); + fprintf(stderr, "cannot allocate storage for stdin contents\n"); + return NULL; + } + s = ss; + n += fread(s + n, 1, t - n - 1, stdin); + if (n < t - 1) + break; + t *= 2; + } + + if (ferror(stdin)) { + free(s); + fprintf(stderr, "error reading stdin\n"); + return NULL; + } + + s[n] = 0; + return s; +} + +static void usage(void) +{ + fprintf(stderr, "Usage: mujs [options] [script [scriptArgs*]]\n"); + fprintf(stderr, "\t-i: Enter interactive prompt after running code.\n"); + fprintf(stderr, "\t-s: Check strictness.\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + char *input; + js_State *J; + int status = 0; + int strict = 0; + int interactive = 0; + int i, c; + + while ((c = xgetopt(argc, argv, "is")) != -1) { + switch (c) { + default: usage(); break; + case 'i': interactive = 1; break; + case 's': strict = 1; break; + } + } + + J = js_newstate(NULL, NULL, strict ? JS_STRICT : 0); + if (!J) { + fprintf(stderr, "Could not initialize MuJS.\n"); + exit(1); + } + + js_newcfunction(J, jsB_gc, "gc", 0); + js_setglobal(J, "gc"); + + js_newcfunction(J, jsB_load, "load", 1); + js_setglobal(J, "load"); + + js_newcfunction(J, jsB_compile, "compile", 2); + js_setglobal(J, "compile"); + + js_newcfunction(J, jsB_print, "print", 0); + js_setglobal(J, "print"); + + js_newcfunction(J, jsB_write, "write", 0); + js_setglobal(J, "write"); + + js_newcfunction(J, jsB_read, "read", 1); + js_setglobal(J, "read"); + + js_newcfunction(J, jsB_readline, "readline", 0); + js_setglobal(J, "readline"); + + js_newcfunction(J, jsB_repr, "repr", 0); + js_setglobal(J, "repr"); + + js_newcfunction(J, jsB_quit, "quit", 1); + js_setglobal(J, "quit"); + + js_dostring(J, require_js); + js_dostring(J, stacktrace_js); + js_dostring(J, console_js); + + if (xoptind == argc) { + interactive = 1; + } else { + c = xoptind++; + + js_newarray(J); + i = 0; + while (xoptind < argc) { + js_pushstring(J, argv[xoptind++]); + js_setindex(J, -2, i++); + } + js_setglobal(J, "scriptArgs"); + + if (js_dofile(J, argv[c])) + status = 1; + } + + if (interactive) { + printf("Welcome to MuJS %d.%d.%d.\n", + JS_VERSION_MAJOR, JS_VERSION_MINOR, JS_VERSION_PATCH); + if (isatty(0)) { + using_history(); + rl_bind_key('\t', rl_insert); + input = readline(PS1); + while (input) { + eval_print(J, input); + if (*input) + add_history(input); + free(input); + input = readline(PS1); + } + putchar('\n'); + } else { + input = read_stdin(); + if (!input || !js_dostring(J, input)) + status = 1; + free(input); + } + } + + js_gc(J, 0); + js_freestate(J); + + return status; +}
