Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/mujs/jsi.h @ 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/jsi.h Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,868 @@ +#ifndef jsi_h +#define jsi_h + +#include "mujs.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdarg.h> +#include <string.h> +#include <setjmp.h> +#include <math.h> +#include <float.h> +#include <limits.h> + +/* NOTE: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103052 */ +#ifdef __GNUC__ +#if (__GNUC__ >= 6) +#pragma GCC optimize ("no-ipa-pure-const") +#endif +#endif + +/* Microsoft Visual C */ +#ifdef _MSC_VER +#pragma warning(disable:4996) /* _CRT_SECURE_NO_WARNINGS */ +#pragma warning(disable:4244) /* implicit conversion from double to int */ +#pragma warning(disable:4267) /* implicit conversion of int to smaller int */ +#pragma warning(disable:4090) /* broken const warnings */ +#define inline __inline +#if _MSC_VER < 1900 /* MSVC 2015 */ +#define snprintf jsW_snprintf +#define vsnprintf jsW_vsnprintf +static int jsW_vsnprintf(char *str, size_t size, const char *fmt, va_list ap) +{ + int n; + n = _vsnprintf(str, size, fmt, ap); + str[size-1] = 0; + return n; +} +static int jsW_snprintf(char *str, size_t size, const char *fmt, ...) +{ + int n; + va_list ap; + va_start(ap, fmt); + n = jsW_vsnprintf(str, size, fmt, ap); + va_end(ap); + return n; +} +#endif +#if _MSC_VER <= 1700 /* <= MSVC 2012 */ +#define isnan(x) _isnan(x) +#define isinf(x) (!_finite(x)) +#define isfinite(x) _finite(x) +static __inline int signbit(double x) { __int64 i; memcpy(&i, &x, 8); return i>>63; } +#define INFINITY (DBL_MAX+DBL_MAX) +#define NAN (INFINITY-INFINITY) +#endif +#endif + +#define soffsetof(x,y) ((int)offsetof(x,y)) +#define nelem(a) (int)(sizeof (a) / sizeof (a)[0]) + +void *js_malloc(js_State *J, int size); +void *js_realloc(js_State *J, void *ptr, int size); +void js_free(js_State *J, void *ptr); + +typedef union js_Value js_Value; +typedef struct js_Regexp js_Regexp; +typedef struct js_Object js_Object; +typedef struct js_String js_String; +typedef struct js_Ast js_Ast; +typedef struct js_Function js_Function; +typedef struct js_Environment js_Environment; +typedef struct js_StringNode js_StringNode; +typedef struct js_Jumpbuf js_Jumpbuf; +typedef struct js_StackTrace js_StackTrace; + +/* Limits */ + +#ifndef JS_STACKSIZE +#define JS_STACKSIZE 4096 /* value stack size */ +#endif +#ifndef JS_ENVLIMIT +#define JS_ENVLIMIT 1024 /* environment stack size */ +#endif +#ifndef JS_TRYLIMIT +#define JS_TRYLIMIT 64 /* exception stack size */ +#endif + +#ifndef JS_ARRAYLIMIT +#define JS_ARRAYLIMIT (1<<26) /* limit arrays to 64M entries (1G of flat array data) */ +#endif + +#ifndef JS_GCFACTOR +/* + * GC will try to trigger when memory usage is this value times the minimum + * needed memory. E.g. if there are 100 remaining objects after GC and this + * value is 5.0, then the next GC will trigger when the overall number is 500. + * I.e. a value of 5.0 aims at 80% garbage, 20% remain-used on each GC. + * The bigger the value the less impact GC has on overall performance, but more + * memory is used and individual GC pauses are longer (but fewer). + */ +#define JS_GCFACTOR 5.0 /* memory overhead factor >= 1.0 */ +#endif + +#ifndef JS_ASTLIMIT +#define JS_ASTLIMIT 400 /* max nested expressions */ +#endif + +#ifndef JS_STRLIMIT +#define JS_STRLIMIT (1<<28) /* max string length */ +#endif + +/* instruction size -- change to int if you get integer overflow syntax errors */ + +#ifdef JS_INSTRUCTION +typedef JS_INSTRUCTION js_Instruction; +#else +typedef unsigned short js_Instruction; +#endif + +/* String interning */ + +char *js_strdup(js_State *J, const char *s); +const char *js_intern(js_State *J, const char *s); +void jsS_dumpstrings(js_State *J); +void jsS_freestrings(js_State *J); + +/* Portable strtod and printf float formatting */ + +void js_fmtexp(char *p, int e); +int js_grisu2(double v, char *buffer, int *K); +double js_strtod(const char *as, char **aas); + +double js_strtol(const char *s, char **ep, int radix); + +/* Private stack functions */ + +void js_newarguments(js_State *J); +void js_newfunction(js_State *J, js_Function *function, js_Environment *scope); +void js_newscript(js_State *J, js_Function *function, js_Environment *scope); +void js_loadeval(js_State *J, const char *filename, const char *source); + +js_Regexp *js_toregexp(js_State *J, int idx); +int js_isarrayindex(js_State *J, const char *str, int *idx); +int js_runeat(js_State *J, const char *s, int i); +int js_utflen(const char *s); +int js_utfptrtoidx(const char *s, const char *p); + +void js_dup(js_State *J); +void js_dup2(js_State *J); +void js_rot2(js_State *J); +void js_rot3(js_State *J); +void js_rot4(js_State *J); +void js_rot2pop1(js_State *J); +void js_rot3pop2(js_State *J); +void js_dup1rot3(js_State *J); +void js_dup1rot4(js_State *J); + +void js_RegExp_prototype_exec(js_State *J, js_Regexp *re, const char *text); + +void js_trap(js_State *J, int pc); /* dump stack and environment to stdout */ + +struct js_StackTrace +{ + const char *name; + const char *file; + int line; +}; + +/* Exception handling */ + +struct js_Jumpbuf +{ + jmp_buf buf; + js_Environment *E; + int envtop; + int tracetop; + int top, bot; + int strict; + js_Instruction *pc; +}; + +void *js_savetrypc(js_State *J, js_Instruction *pc); + +#define js_trypc(J, PC) \ + setjmp(js_savetrypc(J, PC)) + +/* String buffer */ + +typedef struct js_Buffer { int n, m; char s[64]; } js_Buffer; + +void js_putc(js_State *J, js_Buffer **sbp, int c); +void js_puts(js_State *J, js_Buffer **sb, const char *s); +void js_putm(js_State *J, js_Buffer **sb, const char *s, const char *e); + +/* State struct */ + +struct js_State +{ + void *actx; + void *uctx; + js_Alloc alloc; + js_Report report; + js_Panic panic; + + js_StringNode *strings; + + int default_strict; + int strict; + + /* parser input source */ + const char *filename; + const char *source; + int line; + + /* lexer state */ + struct { char *text; int len, cap; } lexbuf; + int lexline; + int lexchar; + int lasttoken; + int newline; + + /* parser state */ + int astdepth; + int lookahead; + const char *text; + double number; + js_Ast *gcast; /* list of allocated nodes to free after parsing */ + + /* runtime environment */ + js_Object *Object_prototype; + js_Object *Array_prototype; + js_Object *Function_prototype; + js_Object *Boolean_prototype; + js_Object *Number_prototype; + js_Object *String_prototype; + js_Object *RegExp_prototype; + js_Object *Date_prototype; + + js_Object *Error_prototype; + js_Object *EvalError_prototype; + js_Object *RangeError_prototype; + js_Object *ReferenceError_prototype; + js_Object *SyntaxError_prototype; + js_Object *TypeError_prototype; + js_Object *URIError_prototype; + + unsigned int seed; /* Math.random seed */ + + char scratch[12]; /* scratch buffer for iterating over array indices */ + + int nextref; /* for js_ref use */ + js_Object *R; /* registry of hidden values */ + js_Object *G; /* the global object */ + js_Environment *E; /* current environment scope */ + js_Environment *GE; /* global environment scope (at the root) */ + + /* execution stack */ + int top, bot; + js_Value *stack; + + /* garbage collector list */ + int gcpause; + int gcmark; + unsigned int gccounter, gcthresh; + js_Environment *gcenv; + js_Function *gcfun; + js_Object *gcobj; + js_String *gcstr; + + js_Object *gcroot; /* gc scan list */ + + /* environments on the call stack but currently not in scope */ + int envtop; + js_Environment *envstack[JS_ENVLIMIT]; + + /* debug info stack trace */ + int tracetop; + js_StackTrace trace[JS_ENVLIMIT]; + + /* exception stack */ + int trytop; + js_Jumpbuf trybuf[JS_TRYLIMIT]; +}; + +/* Values */ + +typedef struct js_Property js_Property; +typedef struct js_Iterator js_Iterator; + +/* Hint to ToPrimitive() */ +enum { + JS_HNONE, + JS_HNUMBER, + JS_HSTRING +}; + +enum js_Type { + JS_TSHRSTR, /* type tag doubles as string zero-terminator */ + JS_TUNDEFINED, + JS_TNULL, + JS_TBOOLEAN, + JS_TNUMBER, + JS_TLITSTR, + JS_TMEMSTR, + JS_TOBJECT, +}; + +enum js_Class { + JS_COBJECT, + JS_CARRAY, + JS_CFUNCTION, + JS_CSCRIPT, /* function created from global/eval code */ + JS_CCFUNCTION, /* built-in function */ + JS_CERROR, + JS_CBOOLEAN, + JS_CNUMBER, + JS_CSTRING, + JS_CREGEXP, + JS_CDATE, + JS_CMATH, + JS_CJSON, + JS_CARGUMENTS, + JS_CITERATOR, + JS_CUSERDATA, +}; + +/* + Short strings abuse the js_Value struct. By putting the type tag in the + last byte, and using 0 as the tag for short strings, we can use the + entire js_Value as string storage by letting the type tag serve double + purpose as the string zero terminator. +*/ + +union js_Value +{ + struct { + char pad[15]; + char type; /* type tag overlaps with final byte of shrstr */ + } t; + union { + char shrstr[16]; + int boolean; + double number; + const char *litstr; + js_String *memstr; + js_Object *object; + } u; +}; + +struct js_String +{ + js_String *gcnext; + char gcmark; + char p[1]; +}; + +struct js_Regexp +{ + void *prog; + char *source; + unsigned short flags; + unsigned short last; +}; + +struct js_Object +{ + enum js_Class type; + int extensible; + js_Property *properties; + int count; /* number of properties, for array sparseness check */ + js_Object *prototype; + union { + int boolean; + double number; + struct { + int length; + char *string; + char shrstr[16]; + } s; + struct { + int length; /* actual length */ + int simple; /* true if array has only non-sparse array properties */ + int flat_length; /* used length of simple array part */ + int flat_capacity; /* allocated length of simple array part */ + js_Value *array; + } a; + struct { + js_Function *function; + js_Environment *scope; + } f; + struct { + const char *name; + js_CFunction function; + js_CFunction constructor; + int length; + void *data; + js_Finalize finalize; + } c; + js_Regexp r; + struct { + js_Object *target; + int i, n; /* for array part */ + js_Iterator *head, *current; /* for object part */ + } iter; + struct { + const char *tag; + void *data; + js_HasProperty has; + js_Put put; + js_Delete delete; + js_Finalize finalize; + } user; + } u; + js_Object *gcnext; /* allocation list */ + js_Object *gcroot; /* scan list */ + int gcmark; +}; + +struct js_Property +{ + js_Property *left, *right; + int level; + int atts; + js_Value value; + js_Object *getter; + js_Object *setter; + char name[1]; +}; + +struct js_Iterator +{ + js_Iterator *next; + char name[1]; +}; + +struct js_Environment +{ + js_Environment *outer; + js_Object *variables; + + js_Environment *gcnext; + int gcmark; +}; + +/* jsrun.c */ +js_Environment *jsR_newenvironment(js_State *J, js_Object *variables, js_Environment *outer); +js_String *jsV_newmemstring(js_State *J, const char *s, int n); +js_Value *js_tovalue(js_State *J, int idx); +void js_toprimitive(js_State *J, int idx, int hint); +js_Object *js_toobject(js_State *J, int idx); +void js_pushvalue(js_State *J, js_Value v); +void js_pushobject(js_State *J, js_Object *v); +void jsR_unflattenarray(js_State *J, js_Object *obj); + +/* jsvalue.c */ +int jsV_toboolean(js_State *J, js_Value *v); +double jsV_tonumber(js_State *J, js_Value *v); +double jsV_tointeger(js_State *J, js_Value *v); +const char *jsV_tostring(js_State *J, js_Value *v); +js_Object *jsV_toobject(js_State *J, js_Value *v); +void jsV_toprimitive(js_State *J, js_Value *v, int preferred); + +const char *js_itoa(char *buf, int a); +double js_stringtofloat(const char *s, char **ep); +int jsV_numbertointeger(double n); +int jsV_numbertoint32(double n); +unsigned int jsV_numbertouint32(double n); +short jsV_numbertoint16(double n); +unsigned short jsV_numbertouint16(double n); +const char *jsV_numbertostring(js_State *J, char buf[32], double number); +double jsV_stringtonumber(js_State *J, const char *string); + +/* jsproperty.c */ +js_Object *jsV_newobject(js_State *J, enum js_Class type, js_Object *prototype); +js_Property *jsV_getownproperty(js_State *J, js_Object *obj, const char *name); +js_Property *jsV_getpropertyx(js_State *J, js_Object *obj, const char *name, int *own); +js_Property *jsV_getproperty(js_State *J, js_Object *obj, const char *name); +js_Property *jsV_setproperty(js_State *J, js_Object *obj, const char *name); +js_Property *jsV_nextproperty(js_State *J, js_Object *obj, const char *name); +void jsV_delproperty(js_State *J, js_Object *obj, const char *name); + +js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own); +const char *jsV_nextiterator(js_State *J, js_Object *iter); + +void jsV_resizearray(js_State *J, js_Object *obj, int newlen); + +void jsV_unflattenarray(js_State *J, js_Object *obj); +void jsV_growarray(js_State *J, js_Object *obj); + +/* Lexer */ + +enum +{ + TK_IDENTIFIER = 256, + TK_NUMBER, + TK_STRING, + TK_REGEXP, + + /* multi-character punctuators */ + TK_LE, + TK_GE, + TK_EQ, + TK_NE, + TK_STRICTEQ, + TK_STRICTNE, + TK_SHL, + TK_SHR, + TK_USHR, + TK_AND, + TK_OR, + TK_ADD_ASS, + TK_SUB_ASS, + TK_MUL_ASS, + TK_DIV_ASS, + TK_MOD_ASS, + TK_SHL_ASS, + TK_SHR_ASS, + TK_USHR_ASS, + TK_AND_ASS, + TK_OR_ASS, + TK_XOR_ASS, + TK_INC, + TK_DEC, + + /* keywords */ + TK_BREAK, + TK_CASE, + TK_CATCH, + TK_CONTINUE, + TK_DEBUGGER, + TK_DEFAULT, + TK_DELETE, + TK_DO, + TK_ELSE, + TK_FALSE, + TK_FINALLY, + TK_FOR, + TK_FUNCTION, + TK_IF, + TK_IN, + TK_INSTANCEOF, + TK_NEW, + TK_NULL, + TK_RETURN, + TK_SWITCH, + TK_THIS, + TK_THROW, + TK_TRUE, + TK_TRY, + TK_TYPEOF, + TK_VAR, + TK_VOID, + TK_WHILE, + TK_WITH, +}; + +int jsY_iswhite(int c); +int jsY_isnewline(int c); +int jsY_ishex(int c); +int jsY_tohex(int c); + +const char *jsY_tokenstring(int token); +int jsY_findword(const char *s, const char **list, int num); + +void jsY_initlex(js_State *J, const char *filename, const char *source); +int jsY_lex(js_State *J); +int jsY_lexjson(js_State *J); + +/* Parser */ + +enum js_AstType +{ + AST_LIST, + AST_FUNDEC, + AST_IDENTIFIER, + + EXP_IDENTIFIER, + EXP_NUMBER, + EXP_STRING, + EXP_REGEXP, + + /* literals */ + EXP_ELISION, /* for array elisions */ + EXP_NULL, + EXP_TRUE, + EXP_FALSE, + EXP_THIS, + + EXP_ARRAY, + EXP_OBJECT, + EXP_PROP_VAL, + EXP_PROP_GET, + EXP_PROP_SET, + + EXP_FUN, + + /* expressions */ + EXP_INDEX, + EXP_MEMBER, + EXP_CALL, + EXP_NEW, + + EXP_POSTINC, + EXP_POSTDEC, + + EXP_DELETE, + EXP_VOID, + EXP_TYPEOF, + EXP_PREINC, + EXP_PREDEC, + EXP_POS, + EXP_NEG, + EXP_BITNOT, + EXP_LOGNOT, + + EXP_MOD, + EXP_DIV, + EXP_MUL, + EXP_SUB, + EXP_ADD, + EXP_USHR, + EXP_SHR, + EXP_SHL, + EXP_IN, + EXP_INSTANCEOF, + EXP_GE, + EXP_LE, + EXP_GT, + EXP_LT, + EXP_STRICTNE, + EXP_STRICTEQ, + EXP_NE, + EXP_EQ, + EXP_BITAND, + EXP_BITXOR, + EXP_BITOR, + EXP_LOGAND, + EXP_LOGOR, + + EXP_COND, + + EXP_ASS, + EXP_ASS_MUL, + EXP_ASS_DIV, + EXP_ASS_MOD, + EXP_ASS_ADD, + EXP_ASS_SUB, + EXP_ASS_SHL, + EXP_ASS_SHR, + EXP_ASS_USHR, + EXP_ASS_BITAND, + EXP_ASS_BITXOR, + EXP_ASS_BITOR, + + EXP_COMMA, + + EXP_VAR, /* var initializer */ + + /* statements */ + STM_BLOCK, + STM_EMPTY, + STM_VAR, + STM_IF, + STM_DO, + STM_WHILE, + STM_FOR, + STM_FOR_VAR, + STM_FOR_IN, + STM_FOR_IN_VAR, + STM_CONTINUE, + STM_BREAK, + STM_RETURN, + STM_WITH, + STM_SWITCH, + STM_THROW, + STM_TRY, + STM_DEBUGGER, + + STM_LABEL, + STM_CASE, + STM_DEFAULT, +}; + +typedef struct js_JumpList js_JumpList; + +struct js_JumpList +{ + enum js_AstType type; + int inst; + js_JumpList *next; +}; + +struct js_Ast +{ + enum js_AstType type; + int line; + js_Ast *parent, *a, *b, *c, *d; + double number; + const char *string; + js_JumpList *jumps; /* list of break/continue jumps to patch */ + int casejump; /* for switch case clauses */ + js_Ast *gcnext; /* next in alloc list */ +}; + +js_Ast *jsP_parsefunction(js_State *J, const char *filename, const char *params, const char *body); +js_Ast *jsP_parse(js_State *J, const char *filename, const char *source); +void jsP_freeparse(js_State *J); + +/* Compiler */ + +enum js_OpCode +{ + OP_POP, /* A -- */ + OP_DUP, /* A -- A A */ + OP_DUP2, /* A B -- A B A B */ + OP_ROT2, /* A B -- B A */ + OP_ROT3, /* A B C -- C A B */ + OP_ROT4, /* A B C D -- D A B C */ + + OP_INTEGER, /* -K- (number-32768) */ + OP_NUMBER, /* -N- <number> */ + OP_STRING, /* -S- <string> */ + OP_CLOSURE, /* -F- <closure> */ + + OP_NEWARRAY, + OP_NEWOBJECT, + OP_NEWREGEXP, /* -S,opts- <regexp> */ + + OP_UNDEF, + OP_NULL, + OP_TRUE, + OP_FALSE, + + OP_THIS, + OP_CURRENT, /* currently executing function object */ + + OP_GETLOCAL, /* -K- <value> */ + OP_SETLOCAL, /* <value> -K- <value> */ + OP_DELLOCAL, /* -K- false */ + + OP_HASVAR, /* -S- ( <value> | undefined ) */ + OP_GETVAR, /* -S- <value> */ + OP_SETVAR, /* <value> -S- <value> */ + OP_DELVAR, /* -S- <success> */ + + OP_IN, /* <name> <obj> -- <exists?> */ + + OP_SKIPARRAY, /* <obj> -- <obj> */ + OP_INITARRAY, /* <obj> <val> -- <obj> */ + OP_INITPROP, /* <obj> <key> <val> -- <obj> */ + OP_INITGETTER, /* <obj> <key> <closure> -- <obj> */ + OP_INITSETTER, /* <obj> <key> <closure> -- <obj> */ + + OP_GETPROP, /* <obj> <name> -- <value> */ + OP_GETPROP_S, /* <obj> -S- <value> */ + OP_SETPROP, /* <obj> <name> <value> -- <value> */ + OP_SETPROP_S, /* <obj> <value> -S- <value> */ + OP_DELPROP, /* <obj> <name> -- <success> */ + OP_DELPROP_S, /* <obj> -S- <success> */ + + OP_ITERATOR, /* <obj> -- <iobj> */ + OP_NEXTITER, /* <iobj> -- ( <iobj> <name> true | false ) */ + + OP_EVAL, /* <args...> -(numargs)- <returnvalue> */ + OP_CALL, /* <closure> <this> <args...> -(numargs)- <returnvalue> */ + OP_NEW, /* <closure> <args...> -(numargs)- <returnvalue> */ + + OP_TYPEOF, + OP_POS, + OP_NEG, + OP_BITNOT, + OP_LOGNOT, + OP_INC, /* <x> -- ToNumber(x)+1 */ + OP_DEC, /* <x> -- ToNumber(x)-1 */ + OP_POSTINC, /* <x> -- ToNumber(x)+1 ToNumber(x) */ + OP_POSTDEC, /* <x> -- ToNumber(x)-1 ToNumber(x) */ + + OP_MUL, + OP_DIV, + OP_MOD, + OP_ADD, + OP_SUB, + OP_SHL, + OP_SHR, + OP_USHR, + OP_LT, + OP_GT, + OP_LE, + OP_GE, + OP_EQ, + OP_NE, + OP_STRICTEQ, + OP_STRICTNE, + OP_JCASE, + OP_BITAND, + OP_BITXOR, + OP_BITOR, + + OP_INSTANCEOF, + + OP_THROW, + + OP_TRY, /* -ADDR- /jump/ or -ADDR- <exception> */ + OP_ENDTRY, + + OP_CATCH, /* push scope chain with exception variable */ + OP_ENDCATCH, + + OP_WITH, + OP_ENDWITH, + + OP_DEBUGGER, + OP_JUMP, + OP_JTRUE, + OP_JFALSE, + OP_RETURN, +}; + +struct js_Function +{ + const char *name; + int script; + int lightweight; + int strict; + int arguments; + int numparams; + + js_Instruction *code; + int codecap, codelen; + + js_Function **funtab; + int funcap, funlen; + + const char **vartab; + int varcap, varlen; + + const char *filename; + int line, lastline; + + js_Function *gcnext; + int gcmark; +}; + +js_Function *jsC_compilefunction(js_State *J, js_Ast *prog); +js_Function *jsC_compilescript(js_State *J, js_Ast *prog, int default_strict); + +/* Builtins */ + +void jsB_init(js_State *J); +void jsB_initobject(js_State *J); +void jsB_initarray(js_State *J); +void jsB_initfunction(js_State *J); +void jsB_initboolean(js_State *J); +void jsB_initnumber(js_State *J); +void jsB_initstring(js_State *J); +void jsB_initregexp(js_State *J); +void jsB_initerror(js_State *J); +void jsB_initmath(js_State *J); +void jsB_initjson(js_State *J); +void jsB_initdate(js_State *J); + +void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n); +void jsB_propn(js_State *J, const char *name, double number); +void jsB_props(js_State *J, const char *name, const char *string); + +#endif
