- "varargs" counterpart to JS_ConvertArguments, JS_ConvertArgumentsVA.

- JS_PushArguments{,VA} and JS_PopArguments to convert a list of C/C++ values
  passed as actual arguments into an 'jsval *argv' on the JS stack.
- Clean up and robustify ConvertArgs test command in the js shell.
This commit is contained in:
brendan%netscape.com 1999-06-08 02:15:57 +00:00
Родитель 4d8ab97905
Коммит 85b69beb44
3 изменённых файлов: 196 добавлений и 51 удалений

Просмотреть файл

@ -158,7 +158,7 @@ GetLine(JSContext *cx, char *bufp, FILE *fh, const char *prompt) {
if (fgets(line, 256, fh) == NULL)
return JS_FALSE;
strcpy(bufp, line);
}
}
return JS_TRUE;
}
@ -186,7 +186,7 @@ Process(JSContext *cx, JSObject *obj, char *filename)
} else {
fh = stdin;
}
if (!isatty(fileno(fh))) {
/*
* It's not interactive - just execute it.
@ -244,19 +244,19 @@ Process(JSContext *cx, JSObject *obj, char *filename)
startline);
if (script) {
JSErrorReporter older;
ok = JS_ExecuteScript(cx, obj, script, &result);
if (ok && result != JSVAL_VOID) {
/* Suppress error reports from JS_ValueToString(). */
older = JS_SetErrorReporter(cx, NULL);
str = JS_ValueToString(cx, result);
JS_SetErrorReporter(cx, older);
if (str)
fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
else
ok = JS_FALSE;
}
}
#if 0
#if JS_HAS_ERROR_EXCEPTIONS
/*
@ -264,7 +264,7 @@ Process(JSContext *cx, JSObject *obj, char *filename)
* been set.
*/
JS_ASSERT(ok || JS_IsExceptionPending(cx));
/*
* Also that any time an exception has been set, we've
* returned failure.
@ -324,7 +324,7 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
filename = NULL;
/* XXX: js -f foo.js should interpret foo.js and then
* drop into interactive mode, but that breaks test
* harness. Just execute foo.js for now.
* harness. Just execute foo.js for now.
*/
isInteractive = JS_FALSE;
i++;
@ -1000,6 +1000,8 @@ EscapeWideString(jschar *w)
unsigned char b, c;
int i, j;
if (!w)
return "";
for (i = j = 0; i < sizeof enuf - 1; i++, j++) {
u = w[j];
if (u == 0)
@ -1033,17 +1035,17 @@ EscapeWideString(jschar *w)
static JSBool
ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSBool b;
jschar c;
int32 i, j;
uint32 u;
jsdouble d, I;
char *s;
JSString *str;
jschar *w;
JSObject *obj;
JSFunction *fun;
jsval v;
JSBool b = JS_FALSE;
jschar c = 0;
int32 i = 0, j = 0;
uint32 u = 0;
jsdouble d = 0, I = 0;
char *s = NULL;
JSString *str = NULL;
jschar *w = NULL;
JSObject *obj = NULL;
JSFunction *fun = NULL;
jsval v = JSVAL_VOID;
if (!JS_ConvertArguments(cx, argc, argv, "b/ciujdIsSWofv*",
&b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj,
@ -1055,9 +1057,9 @@ ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
b, c, (char)c, i, u, j);
fprintf(gOutFile,
"d %g, I %g, s %s, S %s, W %s, obj %s, fun %s, v %s\n",
d, I, s, JS_GetStringBytes(str), EscapeWideString(w),
d, I, s, str ? JS_GetStringBytes(str) : "", EscapeWideString(w),
JS_GetStringBytes(JS_ValueToString(cx, OBJECT_TO_JSVAL(obj))),
JS_GetStringBytes(JS_DecompileFunction(cx, fun, 4)),
fun ? JS_GetStringBytes(JS_DecompileFunction(cx, fun, 4)) : "",
JS_GetStringBytes(JS_ValueToString(cx, v)));
return JS_TRUE;
}
@ -1214,16 +1216,16 @@ static JSPropertySpec its_props[] = {
};
#ifdef JSD_LOWLEVEL_SOURCE
/*
* This facilitates sending source to JSD (the debugger system) in the shell
* where the source is loaded using the JSFILE hack in jsscan. The function
* below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.
* A more normal embedding (e.g. mozilla) loads source itself and can send
/*
* This facilitates sending source to JSD (the debugger system) in the shell
* where the source is loaded using the JSFILE hack in jsscan. The function
* below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.
* A more normal embedding (e.g. mozilla) loads source itself and can send
* source directly to JSD without using this hook scheme.
*/
static void
SendSourceToJSDebugger(const char *filename, uintN lineno,
jschar *str, size_t length,
jschar *str, size_t length,
void **listenerTSData, JSDContext* jsdc)
{
JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData;
@ -1242,7 +1244,7 @@ SendSourceToJSDebugger(const char *filename, uintN lineno,
}
}
if (jsdsrc) {
jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length,
jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length,
JSD_SOURCE_PARTIAL);
}
*listenerTSData = jsdsrc;
@ -1587,7 +1589,7 @@ main(int argc, char **argv)
if (f != NULL) {
int maxArgs = 32; /* arbitrary max !!! */
argc = 1;
argv = malloc(sizeof(char *) * maxArgs);
argv = malloc(sizeof(char *) * maxArgs);
argv[0] = NULL;
while (fgets(argText, 255, f) != NULL) {
/* argText includes '\n' */
@ -1599,7 +1601,7 @@ main(int argc, char **argv)
if (argc >= maxArgs) break;
}
fclose(f);
}
}
gTestResultFile = fopen("results.txt", "w");
}

Просмотреть файл

@ -96,9 +96,20 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
...)
{
va_list ap;
JSBool ok;
va_start(ap, format);
ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
va_end(ap);
return ok;
}
JS_PUBLIC_API(JSBool)
JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
const char *format, va_list ap)
{
uintN i;
JSBool required;
const char *cp;
char c;
JSFunction *fun;
jsdouble d;
@ -106,13 +117,12 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
JSObject *obj;
CHECK_REQUEST(cx);
va_start(ap, format);
i = 0;
required = JS_TRUE;
for (cp = format; *cp != '\0'; cp++) {
if (isspace(*cp))
while ((c = *format++) != '\0') {
if (isspace(c))
continue;
if (*cp == '/') {
if (c == '/') {
required = JS_FALSE;
continue;
}
@ -131,7 +141,7 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
}
break;
}
switch ((c = *cp)) {
switch (c) {
case 'b':
if (!js_ValueToBoolean(cx, argv[i], va_arg(ap, JSBool *)))
return JS_FALSE;
@ -195,18 +205,125 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
break;
default: {
char charBuf[2] = " ";
charBuf[0] = *cp;
charBuf[0] = c;
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR,
charBuf);
return JS_FALSE;
}
}
}
i++;
}
va_end(ap);
return JS_TRUE;
}
JS_PUBLIC_API(jsval *)
JS_PushArguments(JSContext *cx, void **markp, const char *format, ...)
{
va_list ap;
jsval *argv;
va_start(ap, format);
argv = JS_PushArgumentsVA(cx, markp, format, ap);
va_end(ap);
return argv;
}
JS_PUBLIC_API(jsval *)
JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
{
uintN argc;
jsval *argv, *sp;
char c;
const char *cp;
JSString *str;
JSFunction *fun;
CHECK_REQUEST(cx);
*markp = NULL;
argc = 0;
for (cp = format; (c = *cp) != '\0'; cp++) {
if (isspace(c) || c == '*')
continue;
argc++;
}
sp = js_AllocStack(cx, argc, markp);
if (!sp)
return NULL;
argv = sp;
while ((c = *format++) != '\0') {
if (isspace(c) || c == '*')
continue;
switch (c) {
case 'b':
*sp = BOOLEAN_TO_JSVAL(va_arg(ap, JSBool));
break;
case 'c':
*sp = INT_TO_JSVAL(va_arg(ap, uint16));
break;
case 'i':
case 'j':
if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
goto bad;
break;
case 'u':
if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
goto bad;
break;
case 'd':
case 'I':
if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
goto bad;
break;
case 's':
str = JS_NewStringCopyZ(cx, va_arg(ap, char *));
if (!str)
goto bad;
*sp = STRING_TO_JSVAL(str);
break;
case 'W':
str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *));
if (!str)
goto bad;
*sp = STRING_TO_JSVAL(str);
break;
case 'S':
str = va_arg(ap, JSString *);
*sp = STRING_TO_JSVAL(str);
break;
case 'o':
*sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *));
break;
case 'f':
fun = va_arg(ap, JSFunction *);
*sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
break;
case 'v':
*sp = va_arg(ap, jsval);
break;
default: {
char charBuf[2] = " ";
charBuf[0] = c;
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR,
charBuf);
goto bad;
}
}
sp++;
}
return argv;
bad:
js_FreeStack(cx, *markp);
return NULL;
}
JS_PUBLIC_API(void)
JS_PopArguments(JSContext *cx, void *mark)
{
CHECK_REQUEST(cx);
js_FreeStack(cx, mark);
}
JS_PUBLIC_API(JSBool)
JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
{

Просмотреть файл

@ -165,6 +165,33 @@ extern JS_PUBLIC_API(JSBool)
JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
...);
#ifdef va_start
JS_PUBLIC_API(JSBool)
JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
const char *format, va_list ap);
#endif
/*
* Inverse of JS_ConvertArguments: scan format and convert trailing arguments
* into jsvals, GC-rooted if necessary by the JS stack. Return null on error,
* and a pointer to the new argument vector on success. Also return a stack
* mark on success via *markp, in which case the caller must eventually clean
* up by calling JS_PopArguments.
*
* Note that the number of actual arguments supplied is specified exclusively
* by format, so there is no argc parameter.
*/
extern JS_PUBLIC_API(jsval *)
JS_PushArguments(JSContext *cx, void **markp, const char *format, ...);
#ifdef va_start
extern JS_PUBLIC_API(jsval *)
JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap);
#endif
extern JS_PUBLIC_API(void)
JS_PopArguments(JSContext *cx, void *mark);
extern JS_PUBLIC_API(JSBool)
JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp);
@ -1045,18 +1072,17 @@ JS_SetPendingException(JSContext *cx, jsval v);
extern JS_PUBLIC_API(void)
JS_ClearPendingException(JSContext *cx);
/*
* Save the current exception state. This takes a snapshot of the current
* exception state without making any change to that state.
*
* The returned object MUST be later passed to either JS_RestoreExceptionState
* (to restore that saved state) or JS_DropExceptionState (to cleanup the state
* object in case it is not desireable to restore to that state). Both
* JS_RestoreExceptionState and JS_DropExceptionState will destroy the
* JSExceptionState object -- so that object can not be referenced again
* after making either of those calls.
*/
/*
* Save the current exception state. This takes a snapshot of the current
* exception state without making any change to that state.
*
* The returned object MUST be later passed to either JS_RestoreExceptionState
* (to restore that saved state) or JS_DropExceptionState (to cleanup the state
* object in case it is not desireable to restore to that state). Both
* JS_RestoreExceptionState and JS_DropExceptionState will destroy the
* JSExceptionState object -- so that object can not be referenced again
* after making either of those calls.
*/
extern JS_PUBLIC_API(JSExceptionState *)
JS_SaveExceptionState(JSContext *cx);
@ -1093,7 +1119,7 @@ JS_ClearContextThread(JSContext *cx);
* Returns true if a script is executing and its current bytecode is a set
* (assignment) operation.
*
* NOTE: Previously conditional on NETSCAPE_INTERNAL. This function may
* NOTE: Previously conditional on NETSCAPE_INTERNAL. This function may
* be removed in the future.
*/
extern JS_FRIEND_API(JSBool)