/* Simple JSAPI test */

#include "jsapi.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


static JSBool
Print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    uintN i, n;
    JSString *str;

    for (i = n = 0; i < argc; i++) {
	str = JS_ValueToString(cx, argv[i]);
	if (!str)
	    return JS_FALSE;
	printf("%s%s", i ? " " : "", JS_GetStringBytes(str));
	n++;
    }
    if (n)
	putchar('\n');
    return JS_TRUE;
}

static JSFunctionSpec cli_functions[] = {
   {"print",           Print,          0}
};

static JSClass global_class = {
    "global", 0,
    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub
};

static void
js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
    int i, j, k, n;

    fputs("js: ", stderr);
    if (!report) {
	fprintf(stderr, "%s\n", message);
	return;
    }

    if (report->filename)
	fprintf(stderr, "%s, ", report->filename);
    if (report->lineno)
	fprintf(stderr, "line %u: ", report->lineno);
    fputs(message, stderr);
    if (!report->linebuf) {
	putc('\n', stderr);
	return;
    }

    fprintf(stderr, ":\n%s\n", report->linebuf);
    n = report->tokenptr - report->linebuf;
    for (i = j = 0; i < n; i++) {
	if (report->linebuf[i] == '\t') {
	    for (k = (j + 8) & ~7; j < k; j++)
		putc('.', stderr);
	    continue;
	}
	putc('.', stderr);
	j++;
    }
    fputs("^\n", stderr);
}

int main(void)
{
  JSRuntime *js; /* The environment */
  JSContext *cx; /* The context within the environment */
  JSObject *glob;
  js=JS_Init(1024*64);
  cx=JS_NewContext(js,1024*8);
  JS_SetErrorReporter(cx, js_ErrorReporter);
  glob = JS_NewObject(cx, &global_class, NULL, NULL);
  if (!glob)
  {
    printf("Failed to initialise global class\n");
    exit(1);
  }
  if (!JS_DefineFunctions(cx, glob, cli_functions))
  {
    printf("Failed to initialise base CLI functions\n");
    exit(1);
  }
  /* Now some actual code */
  {
    JSString *str=JS_NewString(cx,"Hello world",strlen("Hello world"));
    jsval args=STRING_TO_JSVAL(str);
    jsval answer;
    JS_CallFunctionName(cx,glob,"print",1,&args,&answer);
  }
  /* Test the error reporter... */
  {
    jsval answer;
    JS_CallFunctionName(cx,glob,"wibble",0,NULL,&answer);
  }
  /* Fidy up after us */
  JS_DestroyContext(cx);
  JS_Finish(js);
}
