comparison mupdf-source/thirdparty/mujs/jsrepr.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
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 #include "jsi.h"
2 #include "utf.h"
3
4 static void reprvalue(js_State *J, js_Buffer **sb);
5
6 static void reprnum(js_State *J, js_Buffer **sb, double n)
7 {
8 char buf[40];
9 if (n == 0 && signbit(n))
10 js_puts(J, sb, "-0");
11 else
12 js_puts(J, sb, jsV_numbertostring(J, buf, n));
13 }
14
15 static void reprstr(js_State *J, js_Buffer **sb, const char *s)
16 {
17 static const char *HEX = "0123456789ABCDEF";
18 int i, n;
19 Rune c;
20 js_putc(J, sb, '"');
21 while (*s) {
22 n = chartorune(&c, s);
23 switch (c) {
24 case '"': js_puts(J, sb, "\\\""); break;
25 case '\\': js_puts(J, sb, "\\\\"); break;
26 case '\b': js_puts(J, sb, "\\b"); break;
27 case '\f': js_puts(J, sb, "\\f"); break;
28 case '\n': js_puts(J, sb, "\\n"); break;
29 case '\r': js_puts(J, sb, "\\r"); break;
30 case '\t': js_puts(J, sb, "\\t"); break;
31 default:
32 if (c < ' ') {
33 js_putc(J, sb, '\\');
34 js_putc(J, sb, 'x');
35 js_putc(J, sb, HEX[(c>>4)&15]);
36 js_putc(J, sb, HEX[c&15]);
37 } else if (c < 128) {
38 js_putc(J, sb, c);
39 } else if (c < 0x10000) {
40 js_putc(J, sb, '\\');
41 js_putc(J, sb, 'u');
42 js_putc(J, sb, HEX[(c>>12)&15]);
43 js_putc(J, sb, HEX[(c>>8)&15]);
44 js_putc(J, sb, HEX[(c>>4)&15]);
45 js_putc(J, sb, HEX[c&15]);
46 } else {
47 for (i = 0; i < n; ++i)
48 js_putc(J, sb, s[i]);
49 }
50 break;
51 }
52 s += n;
53 }
54 js_putc(J, sb, '"');
55 }
56
57 #ifndef isalpha
58 #define isalpha(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
59 #endif
60 #ifndef isdigit
61 #define isdigit(c) (c >= '0' && c <= '9')
62 #endif
63
64 static void reprident(js_State *J, js_Buffer **sb, const char *name)
65 {
66 const char *p = name;
67 if (isdigit(*p))
68 while (isdigit(*p))
69 ++p;
70 else if (isalpha(*p) || *p == '_')
71 while (isdigit(*p) || isalpha(*p) || *p == '_')
72 ++p;
73 if (p > name && *p == 0)
74 js_puts(J, sb, name);
75 else
76 reprstr(J, sb, name);
77 }
78
79 static void reprobject(js_State *J, js_Buffer **sb)
80 {
81 const char *key;
82 int i, n;
83
84 n = js_gettop(J) - 1;
85 for (i = 0; i < n; ++i) {
86 if (js_isobject(J, i)) {
87 if (js_toobject(J, i) == js_toobject(J, -1)) {
88 js_puts(J, sb, "{}");
89 return;
90 }
91 }
92 }
93
94 n = 0;
95 js_putc(J, sb, '{');
96 js_pushiterator(J, -1, 1);
97 while ((key = js_nextiterator(J, -1))) {
98 if (n++ > 0)
99 js_puts(J, sb, ", ");
100 reprident(J, sb, key);
101 js_puts(J, sb, ": ");
102 js_getproperty(J, -2, key);
103 reprvalue(J, sb);
104 js_pop(J, 1);
105 }
106 js_pop(J, 1);
107 js_putc(J, sb, '}');
108 }
109
110 static void reprarray(js_State *J, js_Buffer **sb)
111 {
112 int n, i;
113
114 n = js_gettop(J) - 1;
115 for (i = 0; i < n; ++i) {
116 if (js_isobject(J, i)) {
117 if (js_toobject(J, i) == js_toobject(J, -1)) {
118 js_puts(J, sb, "[]");
119 return;
120 }
121 }
122 }
123
124 js_putc(J, sb, '[');
125 n = js_getlength(J, -1);
126 for (i = 0; i < n; ++i) {
127 if (i > 0)
128 js_puts(J, sb, ", ");
129 if (js_hasindex(J, -1, i)) {
130 reprvalue(J, sb);
131 js_pop(J, 1);
132 }
133 }
134 js_putc(J, sb, ']');
135 }
136
137 static void reprfun(js_State *J, js_Buffer **sb, js_Function *fun)
138 {
139 int i;
140 js_puts(J, sb, "function ");
141 js_puts(J, sb, fun->name);
142 js_putc(J, sb, '(');
143 for (i = 0; i < fun->numparams; ++i) {
144 if (i > 0)
145 js_puts(J, sb, ", ");
146 js_puts(J, sb, fun->vartab[i]);
147 }
148 js_puts(J, sb, ") { [byte code] }");
149 }
150
151 static void reprvalue(js_State *J, js_Buffer **sb)
152 {
153 if (js_isundefined(J, -1))
154 js_puts(J, sb, "undefined");
155 else if (js_isnull(J, -1))
156 js_puts(J, sb, "null");
157 else if (js_isboolean(J, -1))
158 js_puts(J, sb, js_toboolean(J, -1) ? "true" : "false");
159 else if (js_isnumber(J, -1))
160 reprnum(J, sb, js_tonumber(J, -1));
161 else if (js_isstring(J, -1))
162 reprstr(J, sb, js_tostring(J, -1));
163 else if (js_isobject(J, -1)) {
164 js_Object *obj = js_toobject(J, -1);
165 switch (obj->type) {
166 default:
167 reprobject(J, sb);
168 break;
169 case JS_CARRAY:
170 reprarray(J, sb);
171 break;
172 case JS_CFUNCTION:
173 case JS_CSCRIPT:
174 reprfun(J, sb, obj->u.f.function);
175 break;
176 case JS_CCFUNCTION:
177 js_puts(J, sb, "function ");
178 js_puts(J, sb, obj->u.c.name);
179 js_puts(J, sb, "() { [native code] }");
180 break;
181 case JS_CBOOLEAN:
182 js_puts(J, sb, "(new Boolean(");
183 js_puts(J, sb, obj->u.boolean ? "true" : "false");
184 js_puts(J, sb, "))");
185 break;
186 case JS_CNUMBER:
187 js_puts(J, sb, "(new Number(");
188 reprnum(J, sb, obj->u.number);
189 js_puts(J, sb, "))");
190 break;
191 case JS_CSTRING:
192 js_puts(J, sb, "(new String(");
193 reprstr(J, sb, obj->u.s.string);
194 js_puts(J, sb, "))");
195 break;
196 case JS_CREGEXP:
197 js_putc(J, sb, '/');
198 js_puts(J, sb, obj->u.r.source);
199 js_putc(J, sb, '/');
200 if (obj->u.r.flags & JS_REGEXP_G) js_putc(J, sb, 'g');
201 if (obj->u.r.flags & JS_REGEXP_I) js_putc(J, sb, 'i');
202 if (obj->u.r.flags & JS_REGEXP_M) js_putc(J, sb, 'm');
203 break;
204 case JS_CDATE:
205 {
206 char buf[40];
207 js_puts(J, sb, "(new Date(");
208 js_puts(J, sb, jsV_numbertostring(J, buf, obj->u.number));
209 js_puts(J, sb, "))");
210 }
211 break;
212 case JS_CERROR:
213 js_puts(J, sb, "(new ");
214 js_getproperty(J, -1, "name");
215 js_puts(J, sb, js_tostring(J, -1));
216 js_pop(J, 1);
217 js_putc(J, sb, '(');
218 if (js_hasproperty(J, -1, "message")) {
219 reprvalue(J, sb);
220 js_pop(J, 1);
221 }
222 js_puts(J, sb, "))");
223 break;
224 case JS_CMATH:
225 js_puts(J, sb, "Math");
226 break;
227 case JS_CJSON:
228 js_puts(J, sb, "JSON");
229 break;
230 case JS_CITERATOR:
231 js_puts(J, sb, "[iterator ");
232 break;
233 case JS_CUSERDATA:
234 js_puts(J, sb, "[userdata ");
235 js_puts(J, sb, obj->u.user.tag);
236 js_putc(J, sb, ']');
237 break;
238 }
239 }
240 }
241
242 void js_repr(js_State *J, int idx)
243 {
244 js_Buffer *sb = NULL;
245 int savebot;
246
247 if (js_try(J)) {
248 js_free(J, sb);
249 js_throw(J);
250 }
251
252 js_copy(J, idx);
253
254 savebot = J->bot;
255 J->bot = J->top - 1;
256 reprvalue(J, &sb);
257 J->bot = savebot;
258
259 js_pop(J, 1);
260
261 js_putc(J, &sb, 0);
262 js_pushstring(J, sb ? sb->s : "undefined");
263
264 js_endtry(J);
265 js_free(J, sb);
266 }
267
268 const char *js_torepr(js_State *J, int idx)
269 {
270 js_repr(J, idx);
271 js_replace(J, idx < 0 ? idx-1 : idx);
272 return js_tostring(J, idx);
273 }
274
275 const char *js_tryrepr(js_State *J, int idx, const char *error)
276 {
277 const char *s;
278 if (js_try(J)) {
279 js_pop(J, 1);
280 return error;
281 }
282 s = js_torepr(J, idx);
283 js_endtry(J);
284 return s;
285 }