mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 394853: countHeap function for js shell and help() cleanup. r=brendan
This commit is contained in:
parent
a79f1f491e
commit
88c81d41b4
480
js/src/js.c
480
js/src/js.c
@ -780,6 +780,163 @@ GCZeal(JSContext *cx, uintN argc, jsval *vp)
|
|||||||
}
|
}
|
||||||
#endif /* JS_GC_ZEAL */
|
#endif /* JS_GC_ZEAL */
|
||||||
|
|
||||||
|
typedef struct JSCountHeapNode JSCountHeapNode;
|
||||||
|
|
||||||
|
struct JSCountHeapNode {
|
||||||
|
void *thing;
|
||||||
|
uint32 kind;
|
||||||
|
JSCountHeapNode *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct JSCountHeapTracer {
|
||||||
|
JSTracer base;
|
||||||
|
JSDHashTable visited;
|
||||||
|
JSBool ok;
|
||||||
|
JSCountHeapNode *traceList;
|
||||||
|
JSCountHeapNode *recycleList;
|
||||||
|
} JSCountHeapTracer;
|
||||||
|
|
||||||
|
static void
|
||||||
|
CountHeapNotify(JSTracer *trc, void *thing, uint32 kind)
|
||||||
|
{
|
||||||
|
JSCountHeapTracer *countTracer;
|
||||||
|
JSDHashEntryStub *entry;
|
||||||
|
JSCountHeapNode *node;
|
||||||
|
|
||||||
|
JS_ASSERT(trc->callback == CountHeapNotify);
|
||||||
|
countTracer = (JSCountHeapTracer *)trc;
|
||||||
|
if (!countTracer->ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
entry = (JSDHashEntryStub *)
|
||||||
|
JS_DHashTableOperate(&countTracer->visited, thing, JS_DHASH_ADD);
|
||||||
|
if (!entry) {
|
||||||
|
JS_ReportOutOfMemory(trc->context);
|
||||||
|
countTracer->ok = JS_FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entry->key)
|
||||||
|
return;
|
||||||
|
entry->key = thing;
|
||||||
|
|
||||||
|
node = countTracer->recycleList;
|
||||||
|
if (node) {
|
||||||
|
countTracer->recycleList = node->next;
|
||||||
|
} else {
|
||||||
|
node = (JSCountHeapNode *) JS_malloc(trc->context, sizeof *node);
|
||||||
|
if (!node) {
|
||||||
|
countTracer->ok = JS_FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node->thing = thing;
|
||||||
|
node->kind = kind;
|
||||||
|
node->next = countTracer->traceList;
|
||||||
|
countTracer->traceList = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
CountHeap(JSContext *cx, uintN argc, jsval *vp)
|
||||||
|
{
|
||||||
|
void* startThing;
|
||||||
|
int32 startTraceKind;
|
||||||
|
jsval v;
|
||||||
|
int32 traceKind, i;
|
||||||
|
JSString *str;
|
||||||
|
char *bytes;
|
||||||
|
JSCountHeapTracer countTracer;
|
||||||
|
JSCountHeapNode *node;
|
||||||
|
size_t counter;
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
const char *name;
|
||||||
|
int32 kind;
|
||||||
|
} traceKindNames[] = {
|
||||||
|
{ "all", -1 },
|
||||||
|
{ "object", JSTRACE_OBJECT },
|
||||||
|
{ "double", JSTRACE_DOUBLE },
|
||||||
|
{ "string", JSTRACE_STRING },
|
||||||
|
{ "function", JSTRACE_FUNCTION },
|
||||||
|
#if JS_HAS_XML_SUPPORT
|
||||||
|
{ "namespace", JSTRACE_NAMESPACE },
|
||||||
|
{ "qname", JSTRACE_QNAME },
|
||||||
|
{ "xml", JSTRACE_XML },
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
startThing = NULL;
|
||||||
|
startTraceKind = 0;
|
||||||
|
if (argc > 0) {
|
||||||
|
v = JS_ARGV(cx, vp)[0];
|
||||||
|
if (JSVAL_IS_TRACEABLE(v)) {
|
||||||
|
startThing = JSVAL_TO_TRACEABLE(v);
|
||||||
|
startTraceKind = JSVAL_TRACE_KIND(v);
|
||||||
|
} else if (v != JSVAL_NULL) {
|
||||||
|
fprintf(gErrFile,
|
||||||
|
"countHeap: argument 1 is not null or a heap-allocated "
|
||||||
|
"thing\n");
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
traceKind = -1;
|
||||||
|
if (argc > 1) {
|
||||||
|
str = JS_ValueToString(cx, JS_ARGV(cx, vp)[1]);
|
||||||
|
if (!str)
|
||||||
|
return JS_FALSE;
|
||||||
|
bytes = JS_GetStringBytes(str);
|
||||||
|
if (!bytes)
|
||||||
|
return JS_FALSE;
|
||||||
|
for (i = 0; ;) {
|
||||||
|
if (strcmp(bytes, traceKindNames[i].name) == 0) {
|
||||||
|
traceKind = traceKindNames[i].kind;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (++i == JS_ARRAY_LENGTH(traceKindNames)) {
|
||||||
|
fprintf(gErrFile,
|
||||||
|
"countHeap: trace kind name '%s' is unknown\n",
|
||||||
|
bytes);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_TRACER_INIT(&countTracer.base, cx, CountHeapNotify);
|
||||||
|
if (!JS_DHashTableInit(&countTracer.visited, JS_DHashGetStubOps(),
|
||||||
|
NULL, sizeof(JSDHashEntryStub),
|
||||||
|
JS_DHASH_DEFAULT_CAPACITY(100))) {
|
||||||
|
JS_ReportOutOfMemory(cx);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
countTracer.ok = JS_TRUE;
|
||||||
|
countTracer.traceList = NULL;
|
||||||
|
countTracer.recycleList = NULL;
|
||||||
|
|
||||||
|
if (!startThing) {
|
||||||
|
JS_TraceRuntime(&countTracer.base);
|
||||||
|
} else {
|
||||||
|
JS_SET_TRACING_NAME(&countTracer.base, "root");
|
||||||
|
JS_CallTracer(&countTracer.base, startThing, startTraceKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
counter = 0;
|
||||||
|
while ((node = countTracer.traceList) != NULL) {
|
||||||
|
if (traceKind == -1 || node->kind == traceKind)
|
||||||
|
counter++;
|
||||||
|
countTracer.traceList = node->next;
|
||||||
|
node->next = countTracer.recycleList;
|
||||||
|
countTracer.recycleList = node;
|
||||||
|
JS_TraceChildren(&countTracer.base, node->thing, node->kind);
|
||||||
|
}
|
||||||
|
while ((node = countTracer.recycleList) != NULL) {
|
||||||
|
countTracer.recycleList = node->next;
|
||||||
|
JS_free(cx, node);
|
||||||
|
}
|
||||||
|
JS_DHashTableFinish(&countTracer.visited);
|
||||||
|
|
||||||
|
return countTracer.ok && JS_NewNumberValue(cx, (jsdouble) counter, vp);
|
||||||
|
}
|
||||||
|
|
||||||
static JSScript *
|
static JSScript *
|
||||||
ValueToScript(JSContext *cx, jsval v)
|
ValueToScript(JSContext *cx, jsval v)
|
||||||
{
|
{
|
||||||
@ -1376,58 +1533,78 @@ DumpStats(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
DumpHeap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
DumpHeap(JSContext *cx, uintN argc, jsval *vp)
|
||||||
{
|
{
|
||||||
char *fileName = NULL;
|
char *fileName;
|
||||||
void* startThing = NULL;
|
jsval v;
|
||||||
uint32 startTraceKind = 0;
|
void* startThing;
|
||||||
void *thingToFind = NULL;
|
uint32 startTraceKind;
|
||||||
size_t maxDepth = (size_t)-1;
|
const char *badTraceArg;
|
||||||
void *thingToIgnore = NULL;
|
void *thingToFind;
|
||||||
jsval *vp;
|
size_t maxDepth;
|
||||||
|
void *thingToIgnore;
|
||||||
FILE *dumpFile;
|
FILE *dumpFile;
|
||||||
JSBool ok;
|
JSBool ok;
|
||||||
|
|
||||||
vp = &argv[0];
|
fileName = NULL;
|
||||||
if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
|
if (argc > 0) {
|
||||||
JSString *str;
|
v = JS_ARGV(cx, vp)[0];
|
||||||
|
if (v != JSVAL_NULL) {
|
||||||
|
JSString *str;
|
||||||
|
|
||||||
str = JS_ValueToString(cx, *vp);
|
str = JS_ValueToString(cx, v);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
*vp = STRING_TO_JSVAL(str);
|
JS_ARGV(cx, vp)[0] = STRING_TO_JSVAL(str);
|
||||||
fileName = JS_GetStringBytes(str);
|
fileName = JS_GetStringBytes(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vp = &argv[1];
|
startThing = NULL;
|
||||||
if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
|
startTraceKind = 0;
|
||||||
if (!JSVAL_IS_TRACEABLE(*vp))
|
if (argc > 1) {
|
||||||
|
v = JS_ARGV(cx, vp)[1];
|
||||||
|
if (JSVAL_IS_TRACEABLE(v)) {
|
||||||
|
startThing = JSVAL_TO_TRACEABLE(v);
|
||||||
|
startTraceKind = JSVAL_TRACE_KIND(v);
|
||||||
|
} else if (v != JSVAL_NULL) {
|
||||||
|
badTraceArg = "start";
|
||||||
goto not_traceable_arg;
|
goto not_traceable_arg;
|
||||||
startThing = JSVAL_TO_TRACEABLE(*vp);
|
}
|
||||||
startTraceKind = JSVAL_TRACE_KIND(*vp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vp = &argv[2];
|
thingToFind = NULL;
|
||||||
if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
|
if (argc > 2) {
|
||||||
if (!JSVAL_IS_TRACEABLE(*vp))
|
v = JS_ARGV(cx, vp)[2];
|
||||||
|
if (JSVAL_IS_TRACEABLE(v)) {
|
||||||
|
thingToFind = JSVAL_TO_TRACEABLE(v);
|
||||||
|
} else if (v != JSVAL_NULL) {
|
||||||
|
badTraceArg = "toFind";
|
||||||
goto not_traceable_arg;
|
goto not_traceable_arg;
|
||||||
thingToFind = JSVAL_TO_TRACEABLE(*vp);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vp = &argv[3];
|
maxDepth = (size_t)-1;
|
||||||
if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
|
if (argc > 3) {
|
||||||
uint32 depth;
|
v = JS_ARGV(cx, vp)[3];
|
||||||
|
if (v != JSVAL_NULL) {
|
||||||
|
uint32 depth;
|
||||||
|
|
||||||
if (!JS_ValueToECMAUint32(cx, *vp, &depth))
|
if (!JS_ValueToECMAUint32(cx, v, &depth))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
maxDepth = depth;
|
maxDepth = depth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vp = &argv[4];
|
thingToIgnore = NULL;
|
||||||
if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
|
if (argc > 4) {
|
||||||
if (!JSVAL_IS_TRACEABLE(*vp))
|
v = JS_ARGV(cx, vp)[4];
|
||||||
|
if (JSVAL_IS_TRACEABLE(v)) {
|
||||||
|
thingToIgnore = JSVAL_TO_TRACEABLE(v);
|
||||||
|
} else if (v != JSVAL_NULL) {
|
||||||
|
badTraceArg = "toIgnore";
|
||||||
goto not_traceable_arg;
|
goto not_traceable_arg;
|
||||||
thingToIgnore = JSVAL_TO_TRACEABLE(*vp);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fileName) {
|
if (!fileName) {
|
||||||
@ -1449,8 +1626,8 @@ DumpHeap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||||||
|
|
||||||
not_traceable_arg:
|
not_traceable_arg:
|
||||||
fprintf(gErrFile,
|
fprintf(gErrFile,
|
||||||
"dumpHeap: argument %u is not null or a heap-allocated thing\n",
|
"dumpHeap: argument '%s' is not null or a heap-allocated thing\n",
|
||||||
(unsigned)(vp - argv));
|
badTraceArg);
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2242,6 +2419,7 @@ static JSFunctionSpec shell_functions[] = {
|
|||||||
JS_FS("help", Help, 0,0,0),
|
JS_FS("help", Help, 0,0,0),
|
||||||
JS_FS("quit", Quit, 0,0,0),
|
JS_FS("quit", Quit, 0,0,0),
|
||||||
JS_FN("gc", GC, 0,0,0,0),
|
JS_FN("gc", GC, 0,0,0,0),
|
||||||
|
JS_FN("countHeap", CountHeap, 0,0,0,0),
|
||||||
#ifdef JS_GC_ZEAL
|
#ifdef JS_GC_ZEAL
|
||||||
JS_FN("gczeal", GCZeal, 1,1,0,0),
|
JS_FN("gczeal", GCZeal, 1,1,0,0),
|
||||||
#endif
|
#endif
|
||||||
@ -2256,7 +2434,7 @@ static JSFunctionSpec shell_functions[] = {
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
JS_FS("dis", Disassemble, 1,0,0),
|
JS_FS("dis", Disassemble, 1,0,0),
|
||||||
JS_FS("dissrc", DisassWithSrc, 1,0,0),
|
JS_FS("dissrc", DisassWithSrc, 1,0,0),
|
||||||
JS_FS("dumpHeap", DumpHeap, 5,0,0),
|
JS_FN("dumpHeap", DumpHeap, 0,0,0,0),
|
||||||
JS_FS("notes", Notes, 1,0,0),
|
JS_FS("notes", Notes, 1,0,0),
|
||||||
JS_FS("tracing", Tracing, 0,0,0),
|
JS_FS("tracing", Tracing, 0,0,0),
|
||||||
JS_FS("stats", DumpStats, 1,0,0),
|
JS_FS("stats", DumpStats, 1,0,0),
|
||||||
@ -2279,68 +2457,139 @@ static JSFunctionSpec shell_functions[] = {
|
|||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
/* NOTE: These must be kept in sync with the above. */
|
static const char shell_help_header[] =
|
||||||
|
"Command Description\n"
|
||||||
|
"======= ===========\n";
|
||||||
|
|
||||||
static char *shell_help_messages[] = {
|
static const char *const shell_help_messages[] = {
|
||||||
"version([number]) Get or set JavaScript version number",
|
"version([number]) Get or set JavaScript version number",
|
||||||
"options([option ...]) Get or toggle JavaScript options",
|
"options([option ...]) Get or toggle JavaScript options",
|
||||||
"load(['foo.js' ...]) Load files named by string arguments",
|
"load(['foo.js' ...]) Load files named by string arguments",
|
||||||
"readline() Read a single line from stdin",
|
"readline() Read a single line from stdin",
|
||||||
"print([exp ...]) Evaluate and print expressions",
|
"print([exp ...]) Evaluate and print expressions",
|
||||||
"help([name ...]) Display usage and help messages",
|
"help([name ...]) Display usage and help messages",
|
||||||
"quit() Quit the shell",
|
"quit() Quit the shell",
|
||||||
"gc() Run the garbage collector",
|
"gc() Run the garbage collector",
|
||||||
|
"countHeap([start[, kind]])\n"
|
||||||
|
" Count the number of live GC things in the heap or things reachable from\n"
|
||||||
|
" start when it is given and is not null. kind is either 'all' (default) to\n"
|
||||||
|
" count all things or one of 'object', 'double', 'string', 'function',\n"
|
||||||
|
" 'qname', 'namespace', 'xml' to count only things of that kind",
|
||||||
#ifdef JS_GC_ZEAL
|
#ifdef JS_GC_ZEAL
|
||||||
"gczeal(level) How zealous the garbage collector should be",
|
"gczeal(level) How zealous the garbage collector should be",
|
||||||
#endif
|
#endif
|
||||||
"trap([fun, [pc,]] exp) Trap bytecode execution",
|
"trap([fun, [pc,]] exp) Trap bytecode execution",
|
||||||
"untrap(fun[, pc]) Remove a trap",
|
"untrap(fun[, pc]) Remove a trap",
|
||||||
"line2pc([fun,] line) Map line number to PC",
|
"line2pc([fun,] line) Map line number to PC",
|
||||||
"pc2line(fun[, pc]) Map PC to line number",
|
"pc2line(fun[, pc]) Map PC to line number",
|
||||||
"stackQuota([number]) Query/set script stack quota",
|
"stackQuota([number]) Query/set script stack quota",
|
||||||
"stringsAreUTF8() Check if strings are UTF-8 encoded",
|
"stringsAreUTF8() Check if strings are UTF-8 encoded",
|
||||||
"testUTF8(mode) Perform UTF-8 tests (modes are 1 to 4)",
|
"testUTF8(mode) Perform UTF-8 tests (modes are 1 to 4)",
|
||||||
"throwError() Throw an error from JS_ReportError",
|
"throwError() Throw an error from JS_ReportError",
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
"dis([fun]) Disassemble functions into bytecodes",
|
"dis([fun]) Disassemble functions into bytecodes",
|
||||||
"dissrc([fun]) Disassemble functions with source lines",
|
"dissrc([fun]) Disassemble functions with source lines",
|
||||||
"dumpHeap([fileName], [start], [toFind], [maxDepth], [toIgnore])\n"
|
"dumpHeap([fileName[, start[, toFind[, maxDepth[, toIgnore]]]]])\n"
|
||||||
" Interface to JS_DumpHeap with output sent to file",
|
" Interface to JS_DumpHeap with output sent to file",
|
||||||
"notes([fun]) Show source notes for functions",
|
"notes([fun]) Show source notes for functions",
|
||||||
"tracing([toggle]) Turn tracing on or off",
|
"tracing([toggle]) Turn tracing on or off",
|
||||||
"stats([string ...]) Dump 'arena', 'atom', 'global' stats",
|
"stats([string ...]) Dump 'arena', 'atom', 'global' stats",
|
||||||
#endif
|
#endif
|
||||||
#ifdef TEST_EXPORT
|
#ifdef TEST_EXPORT
|
||||||
"xport(obj, id) Export identified property from object",
|
"xport(obj, property) Export the given property of obj",
|
||||||
#endif
|
#endif
|
||||||
#ifdef TEST_CVTARGS
|
#ifdef TEST_CVTARGS
|
||||||
"cvtargs(b, c, ...) Test JS_ConvertArguments",
|
"cvtargs(arg1..., arg12) Test argument formater",
|
||||||
#endif
|
#endif
|
||||||
"build() Show build date and time",
|
"build() Show build date and time",
|
||||||
"clear([obj]) Clear properties of object",
|
"clear([obj]) Clear properties of object",
|
||||||
"intern(str) Internalize str in the atom table",
|
"intern(str) Internalize str in the atom table",
|
||||||
"clone(fun[, scope]) Clone function object",
|
"clone(fun[, scope]) Clone function object",
|
||||||
"seal(obj[, deep]) Seal object, or object graph if deep",
|
"seal(obj[, deep]) Seal object, or object graph if deep",
|
||||||
"getpda(obj) Get the property descriptors for obj",
|
"getpda(obj) Get the property descriptors for obj",
|
||||||
"getslx(obj) Get script line extent",
|
"getslx(obj) Get script line extent",
|
||||||
"toint32(n) Testing hook for JS_ValueToInt32",
|
"toint32(n) Testing hook for JS_ValueToInt32",
|
||||||
"evalcx(s[, o]) Evaluate s in optional sandbox object o\n"
|
"evalcx(s[, o])\n"
|
||||||
" if (s == '' && !o) return new o with eager standard classes\n"
|
" Evaluate s in optional sandbox object o\n"
|
||||||
" if (s == 'lazy' && !o) return new o with lazy standard classes",
|
" if (s == '' && !o) return new o with eager standard classes\n"
|
||||||
0
|
" if (s == 'lazy' && !o) return new o with lazy standard classes",
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
/* Help messages must match shell functions. */
|
||||||
ShowHelpHeader(void)
|
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) + 1 ==
|
||||||
{
|
JS_ARRAY_LENGTH(shell_functions));
|
||||||
fprintf(gOutFile, "%-14s %-22s %s\n", "Command", "Usage", "Description");
|
|
||||||
fprintf(gOutFile, "%-14s %-22s %s\n", "=======", "=====", "===========");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
static void
|
static void
|
||||||
ShowHelpForCommand(uintN n)
|
CheckHelpMessages()
|
||||||
{
|
{
|
||||||
fprintf(gOutFile, "%-14.14s %s\n", shell_functions[n].name, shell_help_messages[n]);
|
const char *const *m;
|
||||||
|
const char *lp;
|
||||||
|
|
||||||
|
/* Each message must begin with "function_name(" prefix. */
|
||||||
|
for (m = shell_help_messages; m != JS_ARRAY_END(shell_help_messages); ++m) {
|
||||||
|
lp = strchr(*m, '(');
|
||||||
|
JS_ASSERT(lp);
|
||||||
|
JS_ASSERT(memcmp(shell_functions[m - shell_help_messages].name,
|
||||||
|
*m, lp - *m) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define CheckHelpMessages() ((void) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
uintN i, j;
|
||||||
|
int did_header, did_something;
|
||||||
|
JSType type;
|
||||||
|
JSFunction *fun;
|
||||||
|
JSString *str;
|
||||||
|
const char *bytes;
|
||||||
|
|
||||||
|
fprintf(gOutFile, "%s\n", JS_GetImplementationVersion());
|
||||||
|
if (argc == 0) {
|
||||||
|
fputs(shell_help_header, gOutFile);
|
||||||
|
for (i = 0; shell_functions[i].name; i++)
|
||||||
|
fprintf(gOutFile, "%s\n", shell_help_messages[i]);
|
||||||
|
} else {
|
||||||
|
did_header = 0;
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
did_something = 0;
|
||||||
|
type = JS_TypeOfValue(cx, argv[i]);
|
||||||
|
if (type == JSTYPE_FUNCTION) {
|
||||||
|
fun = JS_ValueToFunction(cx, argv[i]);
|
||||||
|
str = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
|
||||||
|
} else if (type == JSTYPE_STRING) {
|
||||||
|
str = JSVAL_TO_STRING(argv[i]);
|
||||||
|
} else {
|
||||||
|
str = NULL;
|
||||||
|
}
|
||||||
|
if (str) {
|
||||||
|
bytes = JS_GetStringBytes(str);
|
||||||
|
for (j = 0; shell_functions[j].name; j++) {
|
||||||
|
if (!strcmp(bytes, shell_functions[j].name)) {
|
||||||
|
if (!did_header) {
|
||||||
|
did_header = 1;
|
||||||
|
fputs(shell_help_header, gOutFile);
|
||||||
|
}
|
||||||
|
did_something = 1;
|
||||||
|
fprintf(gOutFile, "%s\n", shell_help_messages[j]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!did_something) {
|
||||||
|
str = JS_ValueToString(cx, argv[i]);
|
||||||
|
if (!str)
|
||||||
|
return JS_FALSE;
|
||||||
|
fprintf(gErrFile, "Sorry, no help for %s\n",
|
||||||
|
JS_GetStringBytes(str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSObject *
|
static JSObject *
|
||||||
@ -2377,60 +2626,6 @@ split_setup(JSContext *cx)
|
|||||||
return inner;
|
return inner;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSBool
|
|
||||||
Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
||||||
{
|
|
||||||
uintN i, j;
|
|
||||||
int did_header, did_something;
|
|
||||||
JSType type;
|
|
||||||
JSFunction *fun;
|
|
||||||
JSString *str;
|
|
||||||
const char *bytes;
|
|
||||||
|
|
||||||
fprintf(gOutFile, "%s\n", JS_GetImplementationVersion());
|
|
||||||
if (argc == 0) {
|
|
||||||
ShowHelpHeader();
|
|
||||||
for (i = 0; shell_functions[i].name; i++)
|
|
||||||
ShowHelpForCommand(i);
|
|
||||||
} else {
|
|
||||||
did_header = 0;
|
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
did_something = 0;
|
|
||||||
type = JS_TypeOfValue(cx, argv[i]);
|
|
||||||
if (type == JSTYPE_FUNCTION) {
|
|
||||||
fun = JS_ValueToFunction(cx, argv[i]);
|
|
||||||
str = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
|
|
||||||
} else if (type == JSTYPE_STRING) {
|
|
||||||
str = JSVAL_TO_STRING(argv[i]);
|
|
||||||
} else {
|
|
||||||
str = NULL;
|
|
||||||
}
|
|
||||||
if (str) {
|
|
||||||
bytes = JS_GetStringBytes(str);
|
|
||||||
for (j = 0; shell_functions[j].name; j++) {
|
|
||||||
if (!strcmp(bytes, shell_functions[j].name)) {
|
|
||||||
if (!did_header) {
|
|
||||||
did_header = 1;
|
|
||||||
ShowHelpHeader();
|
|
||||||
}
|
|
||||||
did_something = 1;
|
|
||||||
ShowHelpForCommand(j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!did_something) {
|
|
||||||
str = JS_ValueToString(cx, argv[i]);
|
|
||||||
if (!str)
|
|
||||||
return JS_FALSE;
|
|
||||||
fprintf(gErrFile, "Sorry, no help for %s\n",
|
|
||||||
JS_GetStringBytes(str));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define a JS object called "it". Give it class operations that printf why
|
* Define a JS object called "it". Give it class operations that printf why
|
||||||
* they're being called for tutorial purposes.
|
* they're being called for tutorial purposes.
|
||||||
@ -3177,10 +3372,11 @@ main(int argc, char **argv, char **envp)
|
|||||||
JNIEnv *java_env;
|
JNIEnv *java_env;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gStackBase = (jsuword)&stackDummy;
|
CheckHelpMessages();
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
gStackBase = (jsuword)&stackDummy;
|
||||||
|
|
||||||
#ifdef XP_OS2
|
#ifdef XP_OS2
|
||||||
/* these streams are normally line buffered on OS/2 and need a \n, *
|
/* these streams are normally line buffered on OS/2 and need a \n, *
|
||||||
* so we need to unbuffer then to get a reasonable prompt */
|
* so we need to unbuffer then to get a reasonable prompt */
|
||||||
|
Loading…
Reference in New Issue
Block a user