From a176d21d9e98ec5053d7164d4ed9affd8f2a8656 Mon Sep 17 00:00:00 2001 From: "jband%netscape.com" Date: Fri, 11 Sep 1998 04:04:26 +0000 Subject: [PATCH] (not part of mozilla build) added source hook to jsdbgapi so that debugger can get clean access to source from jsscan when the JSFILE hack is used --- js/ref/js.c | 61 ++++++++++- js/ref/jscntxt.h | 2 + js/ref/jsdbgapi.c | 8 ++ js/ref/jsdbgapi.h | 3 + js/ref/jsprvtd.h | 5 + js/ref/jsscan.c | 56 +--------- js/ref/jsscan.h | 265 ---------------------------------------------- 7 files changed, 83 insertions(+), 317 deletions(-) diff --git a/js/ref/js.c b/js/ref/js.c index 2dbe9833e0f..72331595977 100644 --- a/js/ref/js.c +++ b/js/ref/js.c @@ -1082,6 +1082,63 @@ static JSPropertySpec its_props[] = { {0} }; +#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 + * source directly to JSD without using this hook scheme. + * + * XXX At some future point JSD will understand Unicode source and the + * *very* ugly conversion below will be unnecessary. + */ +static void +SendSourceToJSDebugger(const char *filename, uintN lineno, + jschar *str, size_t length, + void **listenerTSData, JSDContext* jsdc) +{ + JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData; + + if (!jsdsrc) { + if (!filename) + filename = "typein"; + if (1 == lineno) { + jsdsrc = JSD_NewSourceText(jsdc, filename); + } else { + jsdsrc = JSD_FindSourceForURL(jsdc, filename); + if (jsdsrc && JSD_SOURCE_PARTIAL != + JSD_GetSourceStatus(jsdc, jsdsrc)) { + jsdsrc = NULL; + } + } + } + if (jsdsrc) { + /* here we convert our Unicode into a C string to pass to JSD */ +#define JSD_BUF_SIZE 1024 + static char* buf = NULL; + int remaining = length; + + if (!buf) + buf = malloc(JSD_BUF_SIZE); + if (buf) + { + while (remaining && jsdsrc) { + int bytes = PR_MIN(remaining, JSD_BUF_SIZE); + int i; + for (i = 0; i < bytes; i++) + buf[i] = (const char) *(str++); + jsdsrc = JSD_AppendSourceText(jsdc,jsdsrc, + buf, bytes, + JSD_SOURCE_PARTIAL); + remaining -= bytes; + } + } + } + *listenerTSData = jsdsrc; +} +#endif /* JSD_LOWLEVEL_SOURCE */ + static JSBool its_noisy; /* whether to be noisy when finalizing it */ static JSBool @@ -1438,7 +1495,9 @@ main(int argc, char **argv) if (!_jsdc) return 1; JSD_JSContextInUse(_jsdc, cx); - +#ifdef JSD_LOWLEVEL_SOURCE + JS_SetSourceHandler(rt, SendSourceToJSDebugger, _jsdc); +#endif /* JSD_LOWLEVEL_SOURCE */ #ifdef JSDEBUGGER_JAVA_UI _jsdjc = JSDJ_CreateContext(); if (! _jsdjc) diff --git a/js/ref/jscntxt.h b/js/ref/jscntxt.h index 5f2508e36b1..7068c9e03d9 100644 --- a/js/ref/jscntxt.h +++ b/js/ref/jscntxt.h @@ -82,6 +82,8 @@ struct JSRuntime { void *destroyScriptHookData; JSTrapHandler debuggerHandler; void *debuggerHandlerData; + JSSourceHandler sourceHandler; + void *sourceHandlerData; /* More debugging state, see jsdbgapi.c. */ PRCList trapList; diff --git a/js/ref/jsdbgapi.c b/js/ref/jsdbgapi.c index 48b3cdc36d3..965f5faf341 100644 --- a/js/ref/jsdbgapi.c +++ b/js/ref/jsdbgapi.c @@ -806,3 +806,11 @@ JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure) rt->debuggerHandlerData = closure; return JS_TRUE; } + +JS_PUBLIC_API(JSBool) +JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure) +{ + rt->sourceHandler = handler; + rt->sourceHandlerData = closure; + return JS_TRUE; +} diff --git a/js/ref/jsdbgapi.h b/js/ref/jsdbgapi.h index 0db62504c5f..82be27a5927 100644 --- a/js/ref/jsdbgapi.h +++ b/js/ref/jsdbgapi.h @@ -223,6 +223,9 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda); extern JS_PUBLIC_API(JSBool) JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure); +extern JS_PUBLIC_API(JSBool) +JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure); + PR_END_EXTERN_C #endif /* jsdbgapi_h___ */ diff --git a/js/ref/jsprvtd.h b/js/ref/jsprvtd.h index 29c12ebb5c6..b1dac7d2613 100644 --- a/js/ref/jsprvtd.h +++ b/js/ref/jsprvtd.h @@ -96,4 +96,9 @@ typedef void JSScript *script, void *callerdata ); +typedef void +(*JSSourceHandler)(const char *filename, uintN lineno, + jschar *str, size_t length, + void **listenerTSData, void *closure); + #endif /* jsprvtd_h___ */ diff --git a/js/ref/jsscan.c b/js/ref/jsscan.c index edf3206cebb..e32a4c1781c 100644 --- a/js/ref/jsscan.c +++ b/js/ref/jsscan.c @@ -201,9 +201,8 @@ js_NewBufferTokenStream(JSContext *cx, const jschar *base, size_t length) ts->userbuf.base = (jschar *)base; ts->userbuf.limit = (jschar *)base + length; ts->userbuf.ptr = (jschar *)base; -#ifdef JSD_LOWLEVEL_SOURCE - ts->jsdc = JSD_JSDContextForJSContext(cx); -#endif + ts->listener = cx->runtime->sourceHandler; + ts->listenerData = cx->runtime->sourceHandlerData; return ts; } @@ -250,48 +249,6 @@ js_CloseTokenStream(JSContext *cx, JSTokenStream *ts) #endif } -#ifdef JSD_LOWLEVEL_SOURCE -static void -SendSourceToJSDebugger(JSTokenStream *ts, jschar *str, size_t length) -{ - if (!ts->jsdsrc) { - const char* filename = ts->filename ? ts->filename : "typein"; - - if (1 == ts->lineno) { - ts->jsdsrc = JSD_NewSourceText(ts->jsdc, filename); - } else { - ts->jsdsrc = JSD_FindSourceForURL(ts->jsdc, filename); - if (ts->jsdsrc && JSD_SOURCE_PARTIAL != - JSD_GetSourceStatus(ts->jsdc, ts->jsdsrc)) { - ts->jsdsrc = NULL; - } - } - } - if (ts->jsdsrc) { - /* here we convert our Unicode into a C string to pass to JSD */ -#define JSD_BUF_SIZE 1024 - static char* buf = NULL; - int remaining = length; - - if (!buf) - buf = malloc(JSD_BUF_SIZE); - if (buf) - { - while (remaining && ts->jsdsrc) { - int bytes = PR_MIN(remaining, JSD_BUF_SIZE); - int i; - for (i = 0; i < bytes; i++) - buf[i] = (const char) *(str++); - ts->jsdsrc = JSD_AppendSourceText(ts->jsdc,ts->jsdsrc, - buf, bytes, - JSD_SOURCE_PARTIAL); - remaining -= bytes; - } - } - } -} -#endif - static int32 GetChar(JSTokenStream *ts) { @@ -341,12 +298,9 @@ GetChar(JSTokenStream *ts) return EOF; } } - -#ifdef JSD_LOWLEVEL_SOURCE - if (ts->jsdc) - SendSourceToJSDebugger(ts, ts->userbuf.ptr, len); -#endif - + if (ts->listener) + (*ts->listener)(ts->filename, ts->lineno, ts->userbuf.ptr, len, + &ts->listenerTSData, ts->listenerData); /* * Any one of \n, \r, or \r\n ends a line (longest match wins). */ diff --git a/js/ref/jsscan.h b/js/ref/jsscan.h index 4f1a361ab5a..e69de29bb2d 100644 --- a/js/ref/jsscan.h +++ b/js/ref/jsscan.h @@ -1,265 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * The contents of this file are subject to the Netscape Public License - * Version 1.0 (the "NPL"); you may not use this file except in - * compliance with the NPL. You may obtain a copy of the NPL at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the NPL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL - * for the specific language governing rights and limitations under the - * NPL. - * - * The Initial Developer of this code under the NPL is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All Rights - * Reserved. - */ - -#ifndef jsscan_h___ -#define jsscan_h___ -/* - * JS lexical scanner interface. - */ -#include -#ifdef JSFILE -#include -#endif -#include "jsopcode.h" -#include "jsprvtd.h" -#include "jspubtd.h" - -#ifdef JSD_LOWLEVEL_SOURCE -#include "jsdebug.h" -#endif - -PR_BEGIN_EXTERN_C - -typedef enum JSTokenType { - TOK_ERROR = -1, /* well-known as the only code < EOF */ - TOK_EOF = 0, /* end of file */ - TOK_EOL = 1, /* end of line */ - TOK_SEMI = 2, /* semicolon */ - TOK_LB = 3, TOK_RB = 4, /* left and right brackets */ - TOK_LC = 5, TOK_RC = 6, /* left and right curlies (braces) */ - TOK_LP = 7, TOK_RP = 8, /* left and right parentheses */ - TOK_COMMA = 9, /* comma operator */ - TOK_ASSIGN = 10, /* assignment ops (= += -= etc.) */ - TOK_HOOK = 11, TOK_COLON = 12, /* conditional (?:) */ - TOK_OR = 13, /* logical or (||) */ - TOK_AND = 14, /* logical and (&&) */ - TOK_BITOR = 15, /* bitwise-or (|) */ - TOK_BITXOR = 16, /* bitwise-xor (^) */ - TOK_BITAND = 17, /* bitwise-and (&) */ - TOK_EQOP = 18, /* equality ops (== !=) */ - TOK_RELOP = 19, /* relational ops (< <= > >=) */ - TOK_SHOP = 20, /* shift ops (<< >> >>>) */ - TOK_PLUS = 21, /* plus */ - TOK_MINUS = 22, /* minus */ - TOK_STAR = 23, TOK_DIVOP = 24, /* multiply/divide ops (* / %) */ - TOK_UNARYOP = 25, /* unary prefix operator */ - TOK_INC = 26, TOK_DEC = 27, /* increment/decrement (++ --) */ - TOK_DOT = 28, /* member operator (.) */ - TOK_NAME = 29, /* identifier */ - TOK_NUMBER = 30, /* numeric constant */ - TOK_STRING = 31, /* string constant */ - TOK_OBJECT = 32, /* RegExp or other object constant */ - TOK_PRIMARY = 33, /* true, false, null, this, super */ - TOK_FUNCTION = 34, /* function keyword */ - TOK_EXPORT = 35, /* export keyword */ - TOK_IMPORT = 36, /* import keyword */ - TOK_IF = 37, /* if keyword */ - TOK_ELSE = 38, /* else keyword */ - TOK_SWITCH = 39, /* switch keyword */ - TOK_CASE = 40, /* case keyword */ - TOK_DEFAULT = 41, /* default keyword */ - TOK_WHILE = 42, /* while keyword */ - TOK_DO = 43, /* do keyword */ - TOK_FOR = 44, /* for keyword */ - TOK_BREAK = 45, /* break keyword */ - TOK_CONTINUE = 46, /* continue keyword */ - TOK_IN = 47, /* in keyword */ - TOK_VAR = 48, /* var keyword */ - TOK_WITH = 49, /* with keyword */ - TOK_RETURN = 50, /* return keyword */ - TOK_NEW = 51, /* new keyword */ - TOK_DELETE = 52, /* delete keyword */ - TOK_DEFSHARP = 53, /* #n= for object/array initializers */ - TOK_USESHARP = 54, /* #n# for object/array initializers */ - TOK_TRY = 55, /* try keyword */ - TOK_CATCH = 56, /* catch keyword */ - TOK_FINALLY = 57, /* finally keyword */ - TOK_THROW = 58, /* throw keyword */ - TOK_INSTANCEOF = 59, /* instanceof keyword */ - TOK_DEBUGGER = 60, /* debugger keyword */ - TOK_RESERVED, /* reserved keywords */ - TOK_LIMIT /* domain size */ -} JSTokenType; - -#define IS_PRIMARY_TOKEN(tt) \ - ((uintN)((tt) - TOK_NAME) <= (uintN)(TOK_PRIMARY - TOK_NAME)) - -struct JSTokenPtr { - uint16 index; /* index of char in physical line */ - uint16 lineno; /* physical line number */ -}; - -struct JSTokenPos { - JSTokenPtr begin; /* first character and line of token */ - JSTokenPtr end; /* index 1 past last char, last line */ -}; - -struct JSToken { - JSTokenType type; /* char value or above enumerator */ - JSTokenPos pos; /* token position in file */ - jschar *ptr; /* beginning of token in line buffer */ - union { - struct { - JSOp op; /* operator, for minimal parser */ - JSAtom *atom; /* atom table entry */ - } s; - jsdouble dval; /* floating point number */ - } u; -}; - -#define t_op u.s.op -#define t_atom u.s.atom -#define t_dval u.dval - -typedef struct JSTokenBuf { - jschar *base; /* base of line or stream buffer */ - jschar *limit; /* limit for quick bounds check */ - jschar *ptr; /* next char to get, or slot to use */ -} JSTokenBuf; - -#define JS_LINE_LIMIT 256 /* logical line buffer size limit -- - physical line length is unlimited */ - -struct JSTokenStream { - JSToken token; /* last token scanned */ - JSToken pushback; /* pushed-back already-scanned token */ - uintN lineno; /* current line number */ - uintN ungetpos; /* next free char slot in ungetbuf */ - jschar ungetbuf[4]; /* at most 4, for \uXXXX lookahead */ - uintN flags; /* flags -- see below */ - ptrdiff_t linelen; /* physical linebuf segment length */ - ptrdiff_t linepos; /* linebuf offset in physical line */ - JSTokenBuf linebuf; /* line buffer for diagnostics */ - JSTokenBuf userbuf; /* user input buffer if !file */ - JSTokenBuf tokenbuf; /* current token string buffer */ - const char *filename; /* input filename or null */ -#ifdef JSFILE - FILE *file; /* stdio stream if reading from file */ -#endif - JSPrincipals *principals; /* principals associated with given input */ -#ifdef JSD_LOWLEVEL_SOURCE - JSDContext *jsdc; /* used to cram source into debugger */ - JSDSourceText *jsdsrc; /* used to cram source into debugger */ -#endif -}; - -/* JSTokenStream flags */ -#define TSF_ERROR 0x01 /* fatal error while scanning */ -#define TSF_EOF 0x02 /* hit end of file */ -#define TSF_NEWLINES 0x04 /* tokenize newlines */ -#define TSF_REGEXP 0x08 /* looking for a regular expression */ -#define TSF_INTERACTIVE 0x10 /* interactive parsing mode */ -#define TSF_NLFLAG 0x20 /* last linebuf ended with \n */ -#define TSF_CRFLAG 0x40 /* linebuf would have ended with \r */ - -/* - * At most one non-EOF token can be pushed back onto a TokenStream between - * Get or successful Match operations. These macros manipulate the pushback - * token to clear it when changing scanning modes (upon initialzation, after - * errors, or between newline-sensitive and insensitive states). - */ -#define CLEAR_PUSHBACK(ts) ((ts)->pushback.type = TOK_EOF) -#define SCAN_NEWLINES(ts) ((ts)->flags |= TSF_NEWLINES) -#define HIDE_NEWLINES(ts) \ - PR_BEGIN_MACRO \ - (ts)->flags &= ~TSF_NEWLINES; \ - if ((ts)->pushback.type == TOK_EOL) \ - (ts)->pushback.type = TOK_EOF; \ - PR_END_MACRO - -/* Clear ts member that might point above a released cx->tempPool mark. */ -#define RESET_TOKENBUF(ts) ((ts)->tokenbuf.base = (ts)->tokenbuf.limit = NULL) - -/* - * Create a new token stream, either from an input buffer or from a file. - * Return null on file-open or memory-allocation failure. - * - * NB: All of js_New{,Buffer,File}TokenStream() return a pointer to transient - * memory in the current context's temp pool. This memory is deallocated via - * PR_ARENA_RELEASE() after parsing is finished. - */ -extern JSTokenStream * -js_NewTokenStream(JSContext *cx, const jschar *base, size_t length, - const char *filename, uintN lineno, JSPrincipals *principals); - -extern JS_FRIEND_API(JSTokenStream *) -js_NewBufferTokenStream(JSContext *cx, const jschar *base, size_t length); - -#ifdef JSFILE -extern JS_FRIEND_API(JSTokenStream *) -js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp); -#endif - -extern JS_FRIEND_API(JSBool) -js_CloseTokenStream(JSContext *cx, JSTokenStream *ts); - -/* - * Initialize the scanner, installing JS keywords into cx's global scope. - */ -extern JSBool -js_InitScanner(JSContext *cx); - -/* - * Friend-exported API entry point to call a mapping function on each reserved - * identifier in the scanner's keyword table. - */ -extern JS_FRIEND_API(void) -js_MapKeywords(void (*mapfun)(const char *)); - -/* - * Report an error found while scanning ts to a window or other output device - * associated with cx. - */ -extern void -js_ReportCompileError(JSContext *cx, JSTokenStream *ts, uintN flags, - const char *format, ...); - -void -js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, uintN flags, - const uintN errorNumber, ...); - -/* - * Look ahead one token and return its type. - */ -extern JSTokenType -js_PeekToken(JSContext *cx, JSTokenStream *ts); - -extern JSTokenType -js_PeekTokenSameLine(JSContext *cx, JSTokenStream *ts); - -/* - * Get the next token from ts. - */ -extern JSTokenType -js_GetToken(JSContext *cx, JSTokenStream *ts); - -/* - * Push back the last scanned token onto ts. - */ -extern void -js_UngetToken(JSTokenStream *ts); - -/* - * Get the next token from ts if its type is tt. - */ -extern JSBool -js_MatchToken(JSContext *cx, JSTokenStream *ts, JSTokenType tt); - -PR_END_EXTERN_C - -#endif /* jsscan_h___ */