[Pkg-mozext-commits] [adblock-plus] 11/464: Initial import.

David Prévot taffit at moszumanska.debian.org
Tue Jul 22 20:43:57 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository adblock-plus.

commit 2b10021ab2dd896f2daac29756efa73565fd23ae
Author: Joshua Cranmer <Pidgeot18 at gmail.com>
Date:   Fri Jan 23 14:15:34 2009 -0500

    Initial import.
    
    This builds and works.
---
 Makefile         |  24 ++++
 README           |   7 +
 jshydra.c        | 237 +++++++++++++++++++++++++++++++
 jshydra_bridge.c | 233 ++++++++++++++++++++++++++++++
 jshydra_bridge.h |  30 ++++
 jshydra_funcs.c  | 421 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 jshydra_funcs.h  |  39 ++++++
 7 files changed, 991 insertions(+)

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..857d631
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,24 @@
+INCLUDE = -I/src/build/trunk/browser/dist/include/js/ \
+		  -I/src/build/trunk/browser/dist/include/nspr/ -DXP_UNIX \
+	  -I/src/trunk/mozilla/js/src/
+LINK := -L/src/build/trunk/browser/dist/lib -lnspr4 -lm
+
+OBJS := jsapi.o jsarena.o jsarray.o jsatom.o jsbool.o jscntxt.o jsdate.o \
+	jsdbgapi.o jsdhash.o jsdtoa.o jsemit.o jsexn.o jsfun.o jsgc.o jshash.o \
+	jsinterp.o jsinvoke.o jsiter.o jslock.o jslog2.o jslong.o jsmath.o jsnum.o \
+   	jsobj.o json.o jsopcode.o jsparse.o jsprf.o jsregexp.o jsscan.o jsscope.o \
+	jsscript.o jsstr.o jsutil.o jsxdrapi.o jsxml.o prmjtime.o jstracer.o \
+	Assembler.o Fragmento.o LIR.o RegAlloc.o avmplus.o Nativei386.o jsbuiltins.o
+
+OBJS := $(addprefix /src/build/trunk/browser/js/src/, $(OBJS))
+
+jshydra: jshydra.o jshydra_funcs.o jshydra_bridge.o
+	g++ -o jshydra jshydra.o jshydra_funcs.o jshydra_bridge.o $(OBJS) $(LINK)
+
+jshydra.o: jshydra.c
+	gcc -o jshydra.o -g $(INCLUDE) -c jshydra.c
+
+jshydra_funcs.o: jshydra_funcs.c
+	gcc -o jshydra_funcs.o -g $(INCLUDE) -c jshydra_funcs.c
+jshydra_bridge.o: jshydra_bridge.c
+	gcc -o jshydra_bridge.o -g $(INCLUDE) -c jshydra_bridge.c
diff --git a/README b/README
new file mode 100644
index 0000000..7a20499
--- /dev/null
+++ b/README
@@ -0,0 +1,7 @@
+JSHydra static analysis tool
+
+jshydra_builtins.c and jshydra_funcs.c are copied from the dehydra sources with
+minor changes.
+
+The code requires a recent spidermonkey build, as it uses part of the internal
+API. Modify the /src/ paths in Makefile as appropriate to build.
diff --git a/jshydra.c b/jshydra.c
new file mode 100644
index 0000000..b57e314
--- /dev/null
+++ b/jshydra.c
@@ -0,0 +1,237 @@
+typedef int bool;
+
+#include "jsapi.h"
+#include "jsparse.h"
+#include "jscntxt.h"
+#include <stdio.h>
+
+#include "jshydra_bridge.h"
+
+/*static JSRuntime *rt;
+static JSContext *cx;
+static JSObject *globalObject;*/
+
+static char *opcodes[] = {
+#define OPDEF(op, val, name, image, len, use, def, prec, format) \
+	#op,
+#include "jsopcode.tbl"
+#undef OPDEF
+	NULL
+};
+
+void setIntProperty(JSObject *obj, const char *name, int value) {
+	jshydra_defineProperty(cx, obj, name, INT_TO_JSVAL(value));
+}
+void setObjectProperty(JSObject *obj, const char *name, JSObject *value) {
+	jshydra_defineProperty(cx, obj, name, OBJECT_TO_JSVAL(value));
+}
+void setArrayElement(JSObject *array, jsint index, JSObject *value) {
+	jsval argv[1];
+	if (value)
+		argv[0] = OBJECT_TO_JSVAL(value);
+	else
+		argv[0] = JSVAL_NULL;
+	JS_SetElement(cx, array, index, argv);
+}
+
+typedef enum TokenValue {
+	FUNCTION, LIST, TERNARY, BINARY, UNARY, NAME, LEXICAL, APAIR, OBJLITERAL, DOUBLELITERAL, NULLARY, ERROR
+} TokenValue;
+
+TokenValue tokens[] = {
+    ERROR, /*TOK_EOF*/
+    ERROR, /*TOK_EOL*/
+    UNARY, /*TOK_SEMI*/
+    LIST, /*TOK_COMMA*/
+    BINARY, /*TOK_ASSIGN*/
+    BINARY, /*TOK_HOOK*/
+	NAME, /*TOK_COLON*/
+    BINARY, /*TOK_OR*/
+    BINARY, /*TOK_AND*/
+    BINARY, /*TOK_BITOR*/
+    BINARY, /*TOK_BITXOR*/
+    BINARY, /*TOK_BITAND*/
+    BINARY, /*TOK_EQOP*/
+    BINARY, /*TOK_RELOP*/
+    BINARY, /*TOK_SHOP*/
+    BINARY, /*TOK_PLUS*/
+    BINARY, /*TOK_MINUS*/
+    BINARY, /*TOK_STAR*/
+	BINARY, /*TOK_DIVOP*/
+    UNARY, /*TOK_UNARYOP*/
+    UNARY, /*TOK_INC*/
+	UNARY, /*TOK_DEC*/
+    NAME, /*TOK_DOT*/
+    BINARY, /*TOK_LB*/
+	LIST, /*TOK_RB*/
+    LIST, /*TOK_LC*/
+	LIST, /*TOK_RC*/
+    LIST, /*TOK_LP*/
+	UNARY, /*TOK_RP*/
+    NAME, /*TOK_NAME*/
+    DOUBLELITERAL, /*TOK_NUMBER*/
+    NAME, /*TOK_STRING*/
+    NAME, /*TOK_REGEXP*/
+    NULLARY, /*TOK_PRIMARY*/
+    FUNCTION, /*TOK_FUNCTION*/
+    TERNARY, /*TOK_IF*/
+    ERROR, /*TOK_ELSE (not present) */
+    BINARY, /*TOK_SWITCH*/
+    BINARY, /*TOK_CASE*/
+    BINARY, /*TOK_DEFAULT*/
+    BINARY, /*TOK_WHILE*/
+    BINARY, /*TOK_DO*/
+    BINARY, /*TOK_FOR*/
+    NAME, /*TOK_BREAK*/
+    NAME, /*TOK_CONTINUE*/
+    ERROR, /*TOK_IN*/
+    LIST, /*TOK_VAR*/
+    BINARY, /*TOK_WITH*/
+    UNARY, /*TOK_RETURN*/
+    ERROR, /*TOK_NEW*/
+    ERROR, /*TOK_DELETE*/
+    UNARY, /*TOK_DEFSHARP*/
+    NULLARY, /*TOK_USESHARP (use pn_num)*/
+    TERNARY, /*TOK_TRY*/
+    TERNARY, /*TOK_CATCH*/
+    ERROR, /*TOK_FINALLY*/
+    UNARY, /*TOK_THROW*/
+    ERROR, /*TOK_INSTANCEOF*/
+    ERROR, /*TOK_DEBUGGER*/
+    ERROR, /*TOK_XMLSTAGO*/
+    ERROR, /*TOK_XMLETAGO*/
+    ERROR, /*TOK_XMLPTAGC*/
+    ERROR, /*TOK_XMLTAGC*/
+    ERROR, /*TOK_XMLNAME*/
+    ERROR, /*TOK_XMLATTR*/
+    ERROR, /*TOK_XMLSPACE*/
+    ERROR, /*TOK_XMLTEXT*/
+    ERROR, /*TOK_XMLCOMMENT*/
+    ERROR, /*TOK_XMLCDATA*/
+    ERROR, /*TOK_XMLPI*/
+    ERROR, /*TOK_AT*/
+    ERROR, /*TOK_DBLCOLON*/
+    ERROR, /*TOK_ANYNAME*/
+    NAME, /*TOK_DBLDOT*/
+    ERROR, /*TOK_FILTER*/
+    ERROR, /*TOK_XMLELEM*/
+    ERROR, /*TOK_XMLLIST*/
+    ERROR, /*TOK_YIELD*/
+    LIST, /*TOK_ARRAYCOMP*/
+    UNARY, /*TOK_ARRAYPUSH*/
+    NAME, /*TOK_LEXICALSCOPE*/
+    ERROR, /*TOK_LET*/
+    ERROR, /*TOK_SEQ*/
+    ERROR, /*TOK_FORHEAD*/
+    //TOK_RESERVED,
+    //TOK_LIMIT
+	ERROR
+};
+
+JSObject *makeNode(JSParseNode *node) {
+	if (!node)
+		return NULL;
+	JSObject *object = JS_NewObject(cx, &js_node_class, NULL, NULL);
+	setIntProperty(object, "line", node->pn_pos.begin.lineno);
+	setIntProperty(object, "column", node->pn_pos.begin.index);
+	setIntProperty(object, "op", node->pn_op);
+	setIntProperty(object, "type", node->pn_type);
+	switch (tokens[node->pn_type]) {
+	case FUNCTION: {
+		setIntProperty(object, "flags", node->pn_flags);
+		JSObject *array = JS_NewArrayObject(cx, 0, NULL);
+		setArrayElement(array, 0, makeNode(node->pn_body));
+		setObjectProperty(object, "kids", array);
+		break;
+	}
+	case LIST: {
+		JSObject *array = JS_NewArrayObject(cx, 0, NULL);
+		int i = 0;
+		for (node = node->pn_head; node; node = node->pn_next) {
+			setArrayElement(array, i++, makeNode(node));
+		}
+		setObjectProperty(object, "kids", array);
+		break;
+	}
+	case TERNARY: {
+		JSObject *array = JS_NewArrayObject(cx, 0, NULL);
+		setArrayElement(array, 0, makeNode(node->pn_kid1));
+		setArrayElement(array, 1, makeNode(node->pn_kid2));
+		setArrayElement(array, 2, makeNode(node->pn_kid3));
+		setObjectProperty(object, "kids", array);
+		break;
+	}
+	case BINARY: {
+		jshydra_defineProperty(cx, object, "value", node->pn_val);
+		JSObject *array = JS_NewArrayObject(cx, 0, NULL);
+		setArrayElement(array, 0, makeNode(node->pn_left));
+		setArrayElement(array, 1, makeNode(node->pn_right));
+		setObjectProperty(object, "kids", array);
+		break;
+	}
+	case UNARY: {
+		JSObject *array = JS_NewArrayObject(cx, 0, NULL);
+		setArrayElement(array, 0, makeNode(node->pn_kid));
+		setObjectProperty(object, "kids", array);
+		break;
+	}
+	case NAME: {
+		JS_DefineProperty(cx, object, "atom", ATOM_KEY(node->pn_atom), NULL, NULL, JSPROP_READONLY);
+		JSObject *array = JS_NewArrayObject(cx, 0, NULL);
+		setArrayElement(array, 0, makeNode(node->pn_expr));
+		setObjectProperty(object, "kids", array);
+		break;
+	}
+	//case LEXICAL:
+	//case APAIR:
+	//case OBJLITERAL:
+	case DOUBLELITERAL:
+		jshydra_defineProperty(cx, object, "value", DOUBLE_TO_JSVAL(node->pn_dval));
+		break;
+	case NULLARY:
+		break;
+	case ERROR:
+	default:
+		fprintf(stderr, "Unexpected type: %d\n", node->pn_type);
+		break;
+	}
+	return object;
+}
+
+void parseFile(FILE *file, char *filename) {
+	JSParseContext pc;
+	if (!js_InitParseContext(cx, &pc, NULL, NULL, NULL, 0, file, filename, 1))
+		return;
+	JSParseNode *root = js_ParseScript(cx, globalObj, &pc);
+	JSObject *ast = makeNode(root);
+	jsval func = jshydra_getToplevelFunction(cx, "process_js");
+	if (JS_TypeOfValue(cx, func) != JSTYPE_FUNCTION) {
+		fprintf(stderr, "No function process_js!\n");
+		return;
+	}
+	jsval rval, argv[1];
+	argv[0] = OBJECT_TO_JSVAL(ast);
+	JS_CallFunctionValue(cx, globalObj, func, 1, argv, &rval);
+}
+
+int main(int argc, char **argv) {
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s script filename...\n", argv[0]);
+		return -1;
+	}
+	jshydra_init(argv[1]);
+	jshydra_includeScript(cx, argv[1]);
+	argc--;
+	argv++;
+	do {
+		argc--;
+		argv++;
+		FILE *input = fopen(argv[0], "r");
+		if (!input) {
+			fprintf(stderr, "No such file %s\n", argv[0]);
+			continue;
+		}
+		parseFile(input, argv[0]);
+	} while (argc > 1);
+
+}
diff --git a/jshydra_bridge.c b/jshydra_bridge.c
new file mode 100644
index 0000000..d63c02d
--- /dev/null
+++ b/jshydra_bridge.c
@@ -0,0 +1,233 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#include <jsapi.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "jshydra_bridge.h"
+#include "jshydra_funcs.h"
+
+JSRuntime *rt;
+JSContext *cx;
+JSObject *globalObj;
+
+static char *my_dirname (char *path);
+
+JSClass js_node_class = {
+  "JSHydraNode",  /* name */
+  JSCLASS_CONSTRUCT_PROTOTYPE, /* flags */
+  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+  JS_EnumerateStub,JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+void jshydra_init(const char *file) {
+  static JSFunctionSpec shell_functions[] = {
+    {"_print",          Print,          0},
+    {"include",         Include,        1},
+    {"write_file",      WriteFile,      1},
+    {"read_file",       ReadFile,       1},
+    {"diagnostic",      Diagnostic,     0},
+    {"require",         Require,        1},
+    {"hashcode",        Hashcode,       1},
+    {0}
+  };
+
+  //this->fndeclMap = pointer_map_create ();
+  rt = JS_NewRuntime (0x9000000L);
+  cx = JS_NewContext (rt, 8192);
+  JS_BeginRequest(cx);
+
+  //JS_SetContextPrivate (this->cx, this);
+  
+  globalObj = JS_NewObject (cx, NULL, 0, 0);
+  JS_InitStandardClasses (cx, globalObj);
+  /* register error handler */
+  JS_SetErrorReporter (cx, ErrorReporter);
+  xassert (JS_DefineFunctions (cx, globalObj, shell_functions));
+  if (jshydra_getToplevelFunction(cx, "include") == JSVAL_VOID) {
+    fprintf (stderr, "Your version of spidermonkey has broken JS_DefineFunctions, upgrade it or ./configure with another version\n");
+    exit(1);
+  }
+  //this->rootedArgDestArray = 
+  //  JS_NewArrayObject (this->cx, 0, NULL);
+  //JS_AddRoot (this->cx, &this->rootedArgDestArray);
+  // this is to be added at function_decl time
+  //this->rootedFreeArray = JS_NewArrayObject (this->cx, 0, NULL);
+  //JS_DefineElement (this->cx, this->rootedArgDestArray, 0,
+   //                 OBJECT_TO_JSVAL (this->rootedFreeArray),
+  //                  NULL, NULL, JSPROP_ENUMERATE);
+  JS_SetVersion (cx, (JSVersion) 170);
+
+
+  /* Initialize namespace for plugin system stuff. */
+  JSObject *sys = jshydra_defineObjectProperty(cx, globalObj, "sys");
+  /* Set version info */
+  //dehydra_defineStringProperty (this, sys, VERSION_STRING, version_string);
+  //dehydra_defineStringProperty (this, sys, FRONTEND, lang_hooks.name);
+  /* Initialize include path. */
+  jshydra_defineArrayProperty (cx, sys, "include_path", 0);
+
+  char *filename_copy = strdup(file);
+  char *dir = my_dirname(filename_copy);
+  jshydra_appendToPath(cx, dir);
+  char *libdir = malloc(strlen(dir) + strlen("libs") + 2);
+  sprintf(libdir, "%s/%s", dir, "libs");
+  jshydra_appendToPath(cx, libdir);
+  free(libdir);
+  free(filename_copy);
+
+  /* Output filename info */
+  //if (aux_base_name) {
+  //  dehydra_defineStringProperty (this, sys, "aux_base_name", aux_base_name);
+  //}
+  xassert (JS_InitClass(cx, globalObj, NULL
+                        ,&js_node_class , NULL, 0, NULL, NULL, NULL, NULL));
+}
+
+/*int dehydra_startup (Dehydra *this) {
+  return dehydra_includeScript (this, "dehydra.js");
+}*/
+
+int jshydra_includeScript (JSContext *cx, const char *script) {
+  jsval strval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, script));
+  //int key = dehydra_rootObject (this, strval);
+  jsval rval;
+  int ret = !Include (cx, globalObj, 1, &strval, &rval);
+  //dehydra_unrootObject (this, key);
+  return ret;
+}
+
+JSObject *jshydra_getIncludePath (JSContext *cx)
+{
+  jsval sys_val, path_val;
+  JS_GetProperty(cx, globalObj, "sys", &sys_val);
+  JS_GetProperty(cx, JSVAL_TO_OBJECT(sys_val), "include_path", &path_val);
+  return JSVAL_TO_OBJECT(path_val);
+}
+
+/* Append a directory name to the script include path. */
+void jshydra_appendToPath (JSContext *cx, const char *dir) 
+{
+  JSObject *path = jshydra_getIncludePath(cx);
+  unsigned int length = jshydra_getArrayLength(cx, path);
+  JSString *dir_str = JS_NewStringCopyZ(cx, dir);
+  jsval dir_val = STRING_TO_JSVAL(dir_str);
+  JS_DefineElement(cx, path, length, dir_val, NULL, NULL,
+                   JSPROP_ENUMERATE);
+}
+
+/* Avoiding bug 431100. Spec from man 2 dirname */
+static char *my_dirname (char *path) {
+  char *r = strrchr(path, '/');
+  if (!r) {
+    strcpy (path, ".");
+    return path;
+  } else if (r == path && r[1] == 0) {
+    return path; // '/'
+  } else if (r[1] == 0) {
+    // /foo/ foo/ cases
+    *r = 0;
+    return my_dirname (path);
+  }
+  *r = 0;
+  return path;
+}
+
+/* Search the include path for a file matching the given name. The current
+ * directory will be searched last. */
+FILE *jshydra_searchPath (JSContext *cx, const char *filename, char **realname)
+{
+  if (filename && filename[0] != '/') {
+    JSObject *path = jshydra_getIncludePath(cx);
+    int length = jshydra_getArrayLength(cx, path);
+    int i;
+    for (i = 0; i < length; ++i) {
+      jsval val;
+      JS_GetElement(cx, path, i, &val);
+
+      JSString *dir_str = JS_ValueToString(cx, val);
+      if (!dir_str) continue;
+      char *dir = JS_GetStringBytes(dir_str);
+
+      char *buf = malloc(strlen(dir) + strlen(filename) + 2);
+      /* Doing a little extra work here to get rid of unneeded '/'. */
+      char *sep = dir[strlen(dir)-1] == '/' ? "" : "/";
+      sprintf(buf, "%s%s%s", dir, sep, filename);
+      FILE *f = fopen(buf, "r");
+      if (f) {
+        *realname = buf;
+        return f;
+      } else {
+        free(buf);
+      }
+    }
+  }
+  
+  FILE *f = fopen(filename, "r");
+  if (f) {
+    *realname = strdup(filename);
+    return f;
+  }
+
+  return NULL;
+}
+
+jsuint jshydra_getArrayLength (JSContext *cx, JSObject *array) {
+  jsuint length = 0;
+  xassert (JS_GetArrayLength (cx, array, &length));
+  return length;
+}
+
+JSObject *definePropertyObject (JSContext *cx, JSObject *obj,
+                                const char *name, JSClass *clasp,
+                                JSObject *proto, uintN flags) {
+  JSObject *nobj = JS_NewObject (cx, clasp, proto, NULL);
+  JS_DefineProperty (cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, flags);
+  return nobj;
+}
+
+void jshydra_defineProperty (JSContext *cx, JSObject *obj,
+                             char const *name, jsval value)
+{
+  JS_DefineProperty (cx, obj, name, value,
+                     NULL, NULL, JSPROP_ENUMERATE);
+}
+/*
+void dehydra_defineStringProperty (Dehydra *this, JSObject *obj,
+                                   char const *name, char const *value)
+{
+  JSString *str = JS_NewStringCopyZ (this->cx, value);
+  dehydra_defineProperty (this, obj, name, STRING_TO_JSVAL(str));
+}
+*/
+JSObject *jshydra_defineArrayProperty (JSContext *cx, JSObject *obj,
+                                       char const *name, int length) {
+  JSObject *destArray = JS_NewArrayObject (cx, length, NULL);
+  jshydra_defineProperty (cx, obj, name, OBJECT_TO_JSVAL (destArray));
+  return destArray;  
+}
+
+JSObject *jshydra_defineObjectProperty (JSContext *cx, JSObject *obj,
+                                       char const *name) {
+  return definePropertyObject(
+      cx, obj, name, NULL, NULL,
+      JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
+}
+
+/* Load and execute a Javascript file. 
+ * Return:    0 on success
+ *            1 on failure if a Javascript exception is pending
+ *            does not return if a Javascript error is reported
+ * The general behavior of (De|Tree)hydra is to print a message and
+ * exit if a JS error is reported at the top level. But if this function
+ * is called from JS, then the JS_* functions will instead set an
+ * exception, which will be propgated back up to the callers for
+ * eventual handling or exit. */
+
+jsval jshydra_getToplevelFunction(JSContext *cx, char const *name) {
+  jsval val = JSVAL_VOID;
+  return (JS_GetProperty(cx, globalObj, name, &val)
+          && val != JSVAL_VOID
+          && JS_TypeOfValue(cx, val) == JSTYPE_FUNCTION) ? val : JSVAL_VOID;
+}
diff --git a/jshydra_bridge.h b/jshydra_bridge.h
new file mode 100644
index 0000000..735ad6c
--- /dev/null
+++ b/jshydra_bridge.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef JSHYDRA_BRIDGE_H
+#define JSHYDRA_BRIDGE_H
+
+extern JSContext *cx;
+extern JSObject *globalObj;
+
+extern JSClass js_node_class;
+
+void jshydra_init(const char *file);
+FILE *jshydra_searchPath(JSContext *cx, const char *filename, char **realname);
+void jshydra_appendToPath (JSContext *cx, const char *dir);
+int jshydra_includeScript(JSContext *cx, const char *filename);
+
+/* Drop-in replacement for JS_DefineObject, required as a workaround
+ * because JS_DefineObject always sets the parent property. */
+JSObject *definePropertyObject (JSContext *cx, JSObject *obj,
+                               const char *name, JSClass *clasp,
+                               JSObject *proto, uintN flags);
+JSObject *jshydra_defineArrayProperty (JSContext *cx, JSObject *obj,
+                                       char const *name, int length);
+JSObject *jshydra_defineObjectProperty (JSContext *cx, JSObject *obj,
+                                        char const *name);
+void jshydra_defineProperty(JSContext *cx, JSObject *obj,
+                            char const *name, jsval value);
+
+jsuint jshydra_getArrayLength(JSContext *cx, JSObject *array);
+jsval jshydra_getToplevelFunction(JSContext *cx, char const *name);
+
+#endif
diff --git a/jshydra_funcs.c b/jshydra_funcs.c
new file mode 100644
index 0000000..961b03a
--- /dev/null
+++ b/jshydra_funcs.c
@@ -0,0 +1,421 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "jsapi.h"
+#include "jshydra_funcs.h"
+#include "jshydra_bridge.h"
+
+JSBool require_version(JSContext *cx, jsval val) {
+  JSString *version_str = JS_ValueToString(cx, val);
+  if (!version_str) return JS_FALSE;
+  char *version_cstr = JS_GetStringBytes(version_str);
+  JSVersion version = JS_StringToVersion(version_cstr);
+  JSBool retval;
+  if (version == JSVERSION_UNKNOWN) {
+    JS_ReportError(cx, "Invalid version '%s'", version_cstr);
+    retval = JS_FALSE;
+  } else {
+    JS_SetVersion(cx, version);
+    retval = JS_TRUE;
+  }
+  return retval;
+}
+
+JSBool require_option(JSContext *cx, jsval val, uint32 option) {
+  JSBool flag;
+  if (!JS_ValueToBoolean(cx, val, &flag)) return JS_FALSE;
+  if (flag) {
+    JS_SetOptions(cx, JS_GetOptions(cx) | option);
+  } else {
+    JS_SetOptions(cx, JS_GetOptions(cx) & ~option);
+  }
+  return JS_TRUE;
+}
+
+JSBool dispatch_require(JSContext *cx, const char *prop_name, jsval prop_val) {
+  if (strcmp(prop_name, "version") == 0) {
+    return require_version(cx, prop_val);
+  } else if (strcmp(prop_name, "strict") == 0) {
+    return require_option(cx, prop_val, JSOPTION_STRICT);
+  } else if (strcmp(prop_name, "werror") == 0) {
+    return require_option(cx, prop_val, JSOPTION_WERROR);
+  } else if (strcmp(prop_name, "gczeal") == 0) {
+#ifdef JS_GC_ZEAL
+    uintN zeal;
+    if (!JS_ValueToECMAUint32(cx, prop_val, &zeal))
+        return JS_FALSE;
+    JS_SetGCZeal(cx, zeal);
+#else
+#ifdef DEBUG
+    JS_ReportWarning(cx, "gczeal not available: xhydra built with a SpiderMonkey version"
+                     " lacking JS_SetGCZeal");
+#else
+    JS_ReportWarning(cx, "gczeal not available: xhydra built without -DDEBUG");
+#endif //DEBUG
+#endif //JS_GC_ZEAL
+    return JS_TRUE;
+  } else {
+    JS_ReportWarning(cx, "Unrecognized require keyword '%s'", prop_name);
+    return JS_TRUE;
+  }
+}
+
+/* Helper to return the current version as a JS string. */
+jsval get_version(JSContext *cx)
+{
+  const char *version_cstr = JS_VersionToString(JS_GetVersion(cx));
+  if (version_cstr == NULL) {
+    return JSVAL_VOID;
+  }
+  JSString *version_str = JS_NewStringCopyZ(cx, version_cstr);
+  return STRING_TO_JSVAL(version_str);
+}
+
+JSBool Require(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+               jsval *rval)
+{
+  JSObject *args;
+  if (!JS_ConvertArguments(cx, argc, argv, "o", &args)) return JS_FALSE;
+  JSIdArray *prop_ids = JS_Enumerate(cx, args);
+  if (!prop_ids) return JS_FALSE;
+
+  /* Apply the options. */
+  JSBool retval = JS_TRUE;
+  int i;
+  for (i = 0; i < prop_ids->length; ++i) {
+    jsval prop;
+    JSBool rv = JS_IdToValue(cx, prop_ids->vector[i], &prop);
+    argv[argc+1] = prop;
+    xassert(rv);
+    JSString *prop_str = JSVAL_TO_STRING(prop);
+    char *prop_name = JS_GetStringBytes(prop_str);
+    jsval prop_val;
+    rv = JS_GetProperty(cx, args, prop_name, &prop_val);
+    xassert(rv);
+
+    rv = dispatch_require(cx, prop_name, prop_val);
+    if (rv == JS_FALSE) retval = JS_FALSE;
+  }
+  JS_DestroyIdArray(cx, prop_ids);
+  if (!retval) return retval;
+
+  /* Report the now-current options. */
+  JSObject *rvalo = JS_NewObject(cx, NULL, NULL, NULL);
+  if (!rvalo) return JS_FALSE;
+  *rval = OBJECT_TO_JSVAL(rvalo);
+  JS_DefineProperty(
+      cx, rvalo, "version", get_version(cx), NULL, NULL, JSPROP_ENUMERATE);
+  uint32 options = JS_GetOptions(cx);
+  JS_DefineProperty(
+      cx, rvalo, "strict", 
+     (options | JSOPTION_STRICT) ? JSVAL_TRUE : JSVAL_FALSE, 
+      NULL, NULL, JSPROP_ENUMERATE);
+  JS_DefineProperty(
+      cx, rvalo, "werror", 
+     (options | JSOPTION_WERROR) ? JSVAL_TRUE : JSVAL_FALSE, 
+      NULL, NULL, JSPROP_ENUMERATE);
+  return JS_TRUE;
+}
+
+/* Load and run the named script. The last argument is the object to use
+   as "this" when evaluating the script, which is effectively a namespace
+   for the script. */
+static JSBool jshydra_loadScript (JSContext *cx, const char *filename, 
+                                  JSObject *namespace) {
+  /* Read the file. There's a JS function for reading scripts, but Dehydra
+     wants to search for the file in different dirs. */
+  long size = 0;
+  char *realname;
+  FILE *f = jshydra_searchPath(cx, filename, &realname);
+  if (!f) {
+    REPORT_ERROR_1(cx, "Cannot find include file '%s'", filename);
+    return JS_FALSE;
+  }
+  char *content = readEntireFile(f, &size);
+  if (!content) {
+    REPORT_ERROR_1(cx, "Cannot read include file '%s'", realname);
+    free(realname);
+    return JS_FALSE;
+  }
+
+  JSScript *script = JS_CompileScript(cx, namespace,
+                                      content, size, realname, 1);
+  free(realname);
+  if (script == NULL) {
+    xassert(JS_IsExceptionPending(cx));
+    return JS_FALSE;
+  }
+
+  JSObject *sobj = JS_NewScriptObject(cx, script);
+  JS_AddNamedRoot(cx, &sobj, filename);
+  jsval rval;
+  JSBool rv = JS_ExecuteScript(cx, namespace, script, &rval);
+  JS_RemoveRoot(cx, &sobj);
+  if (!rv) {
+    xassert(JS_IsExceptionPending(cx));
+    return JS_FALSE;
+  }
+  return JS_TRUE;
+}
+
+/* should use this function to load all objects to avoid possibity of objects including themselves */
+JSBool Include(JSContext *cx, JSObject *obj, uintN argc,
+               jsval *argv, jsval *rval) {
+  char *filename;
+  JSObject *namespace = globalObj;
+  if (!JS_ConvertArguments(cx, argc, argv, "s/o", &filename, &namespace))
+    return JS_FALSE;
+ 
+  *rval = OBJECT_TO_JSVAL (namespace);
+  JSObject *includedArray = NULL;
+  jsval val;
+  JS_GetProperty(cx, namespace, "_includedArray", &val);
+  if (!JSVAL_IS_OBJECT (val)) {
+    includedArray = JS_NewArrayObject (cx, 0, NULL);
+    jshydra_defineProperty (cx, namespace, "_includedArray",
+                            OBJECT_TO_JSVAL (includedArray));
+  } else {
+    includedArray = JSVAL_TO_OBJECT (val);
+    xassert (JS_CallFunctionName (cx, includedArray, "lastIndexOf",
+                                  1, argv, &val));
+    /* Return if file was already included in this namespace. */
+    if (JSVAL_TO_INT (val) != -1) return JS_TRUE;
+  }
+
+  JS_CallFunctionName (cx, includedArray, "push", 1, argv, rval);
+  return jshydra_loadScript (cx, filename, namespace);
+}
+
+JSBool Diagnostic(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+                  jsval *rval) {
+  JSBool is_error;
+  const char *msg, *file, *error_string;
+  jsint line;
+  JSObject *loc_obj = NULL;
+
+  if (!JS_ConvertArguments(cx, argc, argv, "bs/o", &is_error, &msg, &loc_obj))
+    return JS_FALSE;
+  error_string = is_error ? "error" : "warning";
+  if (loc_obj) {
+    jsval jsfile, jsline;
+    if (JS_GetProperty(cx, loc_obj, "file", &jsfile) &&
+        JS_GetProperty(cx, loc_obj, "line", &jsline)) {
+      file = JS_GetStringBytes(JSVAL_TO_STRING(jsfile));
+      line = JSVAL_TO_INT(jsline);
+      printf("%s:%d: %s: %s\n", file, line, error_string, msg);
+      return JS_TRUE;
+    }
+  }
+
+  printf("%s: %s\n", error_string, msg);
+  return JS_TRUE;
+}
+
+JSBool Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+             jsval *rval)
+{
+  uintN i;
+  for (i = 0; i < argc; i++) {
+    JSString *str = JS_ValueToString(cx, argv[i]);
+    if (!str)
+      return JS_FALSE;
+    printf("%s", JS_GetStringBytes(str));
+  }
+  printf("\n");
+  return JS_TRUE;
+}
+
+JSBool WriteFile(JSContext *cx, JSObject *obj, uintN argc,
+                jsval *argv, jsval *rval) {
+  const char *filename;
+  JSString *str;
+  JSBool rv = JS_ConvertArguments(cx, argc, argv, "sS", &filename, &str);
+  if (!rv) return JS_FALSE;
+
+  FILE *f = fopen (filename, "w");
+  if (!f) {
+    REPORT_ERROR_2(cx, "write_file: error opening file '%s': %s",
+                   filename, strerror(errno));
+    return JS_FALSE;
+  }
+  fwrite (JS_GetStringBytes(str), 1, JS_GetStringLength(str), f);
+  fclose (f);
+  return JS_TRUE;
+}
+
+JSBool ReadFile(JSContext *cx, JSObject *obj, uintN argc,
+                jsval *argv, jsval *rval) {
+  const char *filename;
+  JSBool rv = JS_ConvertArguments(cx, argc, argv, "s", &filename);
+  if (!rv) return JS_FALSE;
+
+  long size = 0;
+  char *buf = readFile (filename, &size);
+  if(!buf) {
+    REPORT_ERROR_2(cx, "read_file: error opening file '%s': %s",
+                   filename, strerror(errno));
+    return JS_FALSE;
+  }
+  *rval = STRING_TO_JSVAL(JS_NewString(cx, buf, size));
+  return JS_TRUE;
+}
+
+/* author: tglek
+   Return the primitive if it's a primitive, otherwise compute a seq #
+   The ES4 spec says that it shouldn't be a pointer(with good reason).
+   A counter is morally wrong because in theory it could loop around and bite me,
+   but I lack in moral values and don't enjoy abusing pointers any further */
+JSBool Hashcode(JSContext *cx, JSObject *obj_this, uintN argc,
+                    jsval *argv, jsval *rval)
+{
+  if (!argc)
+    return JSVAL_FALSE;
+  jsval o = *argv;
+  if (!JSVAL_IS_OBJECT (o)) {
+    *rval = o;
+    return JSVAL_TRUE;
+  }
+  JSObject *obj = JSVAL_TO_OBJECT (*argv);
+  JSBool has_prop;
+  /* Need to check for property first to keep treehydra from getting angry */
+#if JS_VERSION < 180
+#define JS_AlreadyHasOwnProperty JS_HasProperty
+#endif
+  if (JS_AlreadyHasOwnProperty(cx, obj, "_hashcode", &has_prop) && has_prop) {
+    JS_GetProperty(cx, obj, "_hashcode", rval);
+  } else {
+    static int counter = 0;
+    char str[256];
+    jsval val;
+    snprintf (str, sizeof (str), "%x", ++counter);
+    val = STRING_TO_JSVAL (JS_NewStringCopyZ (cx, str));
+    JS_DefineProperty (cx, obj, "_hashcode", val,
+                       NULL, NULL, JSPROP_PERMANENT | JSPROP_READONLY);
+    *rval = val;
+  }
+  return JS_TRUE;
+}
+
+/* Read the entire contents of a file.
+ *      path   path of the file to read
+ *      size   (out) number of bytes of file data read
+ *    return   null-terminated file contents, or NULL on error. Caller
+ *             should free when done. */
+char *readFile(const char *path, long *size) {
+  FILE *f = fopen(path, "r");
+  if (!f) return NULL;
+  return readEntireFile(f, size);
+}
+
+/* Find a file, searching another dir if necessary.  If the file is
+ * found, return a file handle open for reading and store the malloc'd
+ * name where the file was found in realname. Otherwise, return
+ * NULL. */
+FILE *findFile(const char *filename, const char *dir, char **realname) {
+  FILE *f = fopen(filename, "r");
+  if (f) {
+    *realname = strdup(filename);
+    return f;
+  }
+  if (dir && dir[0] && filename[0] && filename[0] != '/') {
+    char *buf = malloc(strlen(dir) + strlen(filename) + 2);
+    /* Doing a little extra work here to get rid of unneeded '/'. */
+    char *sep = dir[strlen(dir)-1] == '/' ? "" : "/";
+    sprintf(buf, "%s%s%s", dir, sep, filename);
+    f = fopen(buf, "r");
+    if (f) {
+      *realname = buf;
+      return f;
+    } else {
+      free(buf);
+    }
+  }
+  return NULL;
+}
+
+char *readEntireFile(FILE *f, long *size) {
+  xassert(f);
+  if (fseek(f, 0, SEEK_END)) return NULL;
+  *size = ftell(f);
+  if (fseek(f, 0, SEEK_SET)) return NULL;
+  char *buf = malloc(*size + 1);
+  xassert(*size == fread(buf, 1, *size, f));
+  buf[*size] = 0;
+  fclose(f);
+  return buf;
+}
+
+/* Report an error.
+ * If we are currently inside JS, we'll report an error to JS. But
+ * otherwise, we'll report it to the user and then exit. */
+void reportError(JSContext *cx, const char *file, int line, 
+                 const char *fmt, ...) 
+{
+  char msg[1024];
+  const int size = sizeof(msg) / sizeof(msg[0]);
+  va_list ap;
+  va_start(ap, fmt);
+  int nw = vsnprintf(msg, size, fmt, ap);
+  va_end(ap);
+  if (nw >= size) msg[size-1] = '\0';
+  
+  if (JS_IsRunning(cx)) {
+    JS_ReportError(cx, "%s (from %s:%d)", msg, file, line);
+  } else {
+    fflush(stdout);
+    fprintf(stderr, "%s:%d: Error: %s\n", file, line, msg);
+    exit(1);
+  }
+}
+
+void
+ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
+{
+  int error = JSREPORT_IS_EXCEPTION(report->flags);
+  jsval exn;
+  fflush(stdout);
+  fprintf(stderr, "%s:%d: ", (report->filename ? report->filename : "NULL"),
+          report->lineno);
+  if (JSREPORT_IS_WARNING(report->flags)) fprintf(stderr, "JS Warning");
+  if (JSREPORT_IS_STRICT(report->flags)) fprintf(stderr, "JS STRICT");
+  if (error) fprintf(stderr, "JS Exception");
+ 
+  fprintf(stderr, ": %s\n", message);
+  if (report->linebuf) {
+    fprintf(stderr, "%s\n", report->linebuf);
+  }
+  if (error && JS_GetPendingException(cx, &exn)
+      && JS_TypeOfValue (cx, exn) == JSTYPE_OBJECT) {
+    jsval stack;
+    /* reformat the spidermonkey stack */
+    JS_GetProperty(cx, JSVAL_TO_OBJECT (exn), "stack", &stack);
+    if (JS_TypeOfValue (cx, stack) == JSTYPE_STRING) {
+      char *str = JS_GetStringBytes (JSVAL_TO_STRING (stack));
+      int counter = 0;
+      do {
+        char *eol = strchr (str, '\n');
+        if (eol)
+          *eol = 0;
+        char *at = strrchr (str, '@');
+        if (!at) break;
+        *at = 0;
+        if (!*str) break;
+        fprintf (stderr, "%s:\t#%d: %s\n", at+1, counter++, str);
+        *at = '@';
+        if (eol) {
+          *eol = '\n';
+          str = eol + 1;
+        } else {
+          break;
+        }
+      } while (*str);
+    }
+  }
+  fflush(stderr);
+  
+  if (!JSREPORT_IS_WARNING(report->flags))
+    exit(1);
+}
diff --git a/jshydra_funcs.h b/jshydra_funcs.h
new file mode 100644
index 0000000..942bbe9
--- /dev/null
+++ b/jshydra_funcs.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef JSHYDRA_FUNCS_H
+#define JSHYDRA_FUNCS_H
+
+/* JS Natives */
+
+#define DH_JSNATIVE(fname) JSBool fname(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+ 
+DH_JSNATIVE(Require);
+DH_JSNATIVE(Include);
+ 
+DH_JSNATIVE(Diagnostic);
+DH_JSNATIVE(Print);
+ 
+DH_JSNATIVE(WriteFile);
+DH_JSNATIVE(ReadFile);
+DH_JSNATIVE(Hashcode);
+
+void ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
+
+/* Related C functions */
+
+char *readFile(const char *path, long *size);
+FILE *findFile(const char *filename, const char *dir, char **realname);
+char *readEntireFile(FILE *f, long *size);
+void  reportError(JSContext *cx, const char *file, int line, 
+                  const char *fmt, ...);
+
+#define REPORT_ERROR_0(cx, fmt) reportError(cx, __FILE__, __LINE__, fmt);
+#define REPORT_ERROR_1(cx, fmt, arg1) reportError(cx, __FILE__, __LINE__, fmt, arg1);
+#define REPORT_ERROR_2(cx, fmt, arg1, arg2) reportError(cx, __FILE__, __LINE__, fmt, arg1, arg1);
+
+#define xassert(cond) \
+  if (!(cond)) { \
+    fprintf(stderr, "%s:%d: Assertion failed:" #cond "\n", __FILE__, __LINE__);\
+    exit(1); \
+  }
+
+#endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/adblock-plus.git



More information about the Pkg-mozext-commits mailing list