void jsonNewLine(JSONFlags flags, const char *whitespace, vcbprintf_callback user_callback, void *user_data) { cbprintf(user_callback, user_data, "\n"); // apply the indent unsigned int indent = flags / JSON_INDENT; while (indent--) cbprintf(user_callback, user_data, whitespace); }
void jslPrintPosition(vcbprintf_callback user_callback, void *user_data, size_t tokenPos) { size_t line,col; jsvGetLineAndCol(lex->sourceVar, tokenPos, &line, &col); if (lex->lineNumberOffset) line += (size_t)lex->lineNumberOffset - 1; cbprintf(user_callback, user_data, "line %d col %d\n", line, col); }
static bool jsfGetJSONForObjectItWithCallback(JsvObjectIterator *it, JSONFlags flags, const char *whitespace, JSONFlags nflags, vcbprintf_callback user_callback, void *user_data, bool first) { bool needNewLine = false; size_t sinceNewLine = 0; while (jsvObjectIteratorHasValue(it) && !jspIsInterrupted()) { JsVar *index = jsvObjectIteratorGetKey(it); JsVar *item = jsvGetValueOfName(index); bool hidden = jsvIsInternalObjectKey(index) || ((flags & JSON_IGNORE_FUNCTIONS) && jsvIsFunction(item)) || ((flags&JSON_NO_UNDEFINED) && jsvIsUndefined(item)) || jsvIsGetterOrSetter(item); if (!hidden) { sinceNewLine++; if (!first) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":","); bool newNeedsNewLine = (flags&JSON_SOME_NEWLINES) && jsonNeedsNewLine(item); if ((flags&JSON_SOME_NEWLINES) && sinceNewLine>JSON_ITEMS_ON_LINE_OBJECT) needNewLine = true; if (flags&JSON_ALL_NEWLINES) { needNewLine = true; newNeedsNewLine = true; } if (needNewLine || newNeedsNewLine) { jsonNewLine(nflags, whitespace, user_callback, user_data); needNewLine = false; sinceNewLine = 0; } bool addQuotes = true; if (flags&JSON_DROP_QUOTES) { if (jsvIsIntegerish(index)) addQuotes = false; else if (jsvIsString(index) && jsvGetStringLength(index)<15) { char buf[16]; jsvGetString(index,buf,sizeof(buf)); if (isIDString(buf)) addQuotes=false; } } cbprintf(user_callback, user_data, addQuotes?"%q%s":"%v%s", index, (flags&JSON_PRETTY)?": ":":"); if (first) first = false; jsfGetJSONWithCallback(item, nflags, whitespace, user_callback, user_data); needNewLine = newNeedsNewLine; } jsvUnLock2(index, item); jsvObjectIteratorNext(it); } return needNewLine; }
void jslPrintTokenLineMarker(vcbprintf_callback user_callback, void *user_data, size_t tokenPos, char *prefix) { size_t line = 1,col = 1; jsvGetLineAndCol(lex->sourceVar, tokenPos, &line, &col); size_t startOfLine = jsvGetIndexFromLineAndCol(lex->sourceVar, line, 1); size_t lineLength = jsvGetCharsOnLine(lex->sourceVar, line); size_t prefixLength = 0; if (prefix) { user_callback(prefix, user_data); prefixLength = strlen(prefix); } if (lineLength>60 && tokenPos-startOfLine>30) { cbprintf(user_callback, user_data, "..."); size_t skipChars = tokenPos-30 - startOfLine; startOfLine += 3+skipChars; if (skipChars<=col) col -= skipChars; else col = 0; lineLength -= skipChars; } // print the string until the end of the line, or 60 chars (whichever is less) int chars = 0; JsvStringIterator it; jsvStringIteratorNew(&it, lex->sourceVar, startOfLine); unsigned char lastch = 0; while (jsvStringIteratorHasChar(&it) && chars<60) { unsigned char ch = (unsigned char)jsvStringIteratorGetChar(&it); if (ch == '\n') break; if (jslNeedSpaceBetween(lastch, ch)) { col++; user_callback(" ", user_data); } char buf[32]; jslFunctionCharAsString(ch, buf, sizeof(buf)); size_t len = strlen(buf); col += len-1; user_callback(buf, user_data); chars++; lastch = ch; jsvStringIteratorNext(&it); } jsvStringIteratorFree(&it); if (lineLength > 60) user_callback("...", user_data); user_callback("\n", user_data); col += prefixLength; while (col-- > 1) user_callback(" ", user_data); user_callback("^\n", user_data); }
void jslPrintTokenLineMarker(vcbprintf_callback user_callback, void *user_data, size_t tokenPos, char *prefix) { size_t line = 1,col = 1; jsvGetLineAndCol(lex->sourceVar, tokenPos, &line, &col); size_t startOfLine = jsvGetIndexFromLineAndCol(lex->sourceVar, line, 1); size_t lineLength = jsvGetCharsOnLine(lex->sourceVar, line); size_t prefixLength = 0; if (prefix) { user_callback(prefix, user_data); prefixLength = strlen(prefix); } if (lineLength>60 && tokenPos-startOfLine>30) { cbprintf(user_callback, user_data, "..."); size_t skipChars = tokenPos-30 - startOfLine; startOfLine += 3+skipChars; col -= skipChars; lineLength -= skipChars; } // print the string until the end of the line, or 60 chars (whichever is lesS) int chars = 0; JsvStringIterator it; jsvStringIteratorNew(&it, lex->sourceVar, startOfLine); while (jsvStringIteratorHasChar(&it) && chars<60) { char ch = jsvStringIteratorGetChar(&it); if (ch == '\n') break; char buf[2]; buf[0] = ch; buf[1] = 0; user_callback(buf, user_data); chars++; jsvStringIteratorNext(&it); } jsvStringIteratorFree(&it); if (lineLength > 60) user_callback("...", user_data); user_callback("\n", user_data); col += prefixLength; while (col-- > 1) user_callback(" ", user_data); user_callback("^\n", user_data); }
/* This is like jsfGetJSONWithCallback, but handles ONLY functions (and does not print the initial 'function' text) */ void jsfGetJSONForFunctionWithCallback(JsVar *var, JSONFlags flags, vcbprintf_callback user_callback, void *user_data) { assert(jsvIsFunction(var)); JsVar *codeVar = 0; // TODO: this should really be in jsvAsString JsvObjectIterator it; jsvObjectIteratorNew(&it, var); bool firstParm = true; cbprintf(user_callback, user_data, "("); while (jsvObjectIteratorHasValue(&it)) { JsVar *child = jsvObjectIteratorGetKey(&it); if (jsvIsFunctionParameter(child)) { if (firstParm) firstParm=false; else cbprintf(user_callback, user_data, ","); cbprintf(user_callback, user_data, "%v", child); } else if (jsvIsString(child) && jsvIsStringEqual(child, JSPARSE_FUNCTION_CODE_NAME)) { codeVar = jsvObjectIteratorGetValue(&it); } jsvUnLock(child); jsvObjectIteratorNext(&it); } jsvObjectIteratorFree(&it); cbprintf(user_callback, user_data, ") "); if (jsvIsNative(var)) { cbprintf(user_callback, user_data, "{ [native code] }"); } else { if (codeVar) { if (flags & JSON_LIMIT) { cbprintf(user_callback, user_data, "{%s}", JSON_LIMIT_TEXT); } else { cbprintf(user_callback, user_data, "%v", codeVar); } } else cbprintf(user_callback, user_data, "{}"); } jsvUnLock(codeVar); }
void jsfGetJSONWithCallback(JsVar *var, JSONFlags flags, const char *whitespace, vcbprintf_callback user_callback, void *user_data) { JSONFlags nflags = flags + JSON_INDENT; // if we add a newline, make sure we indent any subsequent JSON more if (!whitespace) whitespace=" "; if (jsvIsUndefined(var)) { cbprintf(user_callback, user_data, "undefined"); } else { // Use IS_RECURSING flag to stop recursion if (var->flags & JSV_IS_RECURSING) { cbprintf(user_callback, user_data, " ... "); return; } var->flags |= JSV_IS_RECURSING; if (jsvIsArray(var)) { JsVarInt length = jsvGetArrayLength(var); bool limited = (flags&JSON_LIMIT) && (length>(JsVarInt)JSON_LIMIT_AMOUNT); bool needNewLine = false; cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"[ ":"["); JsVarInt lastIndex = -1; bool numeric = true; bool first = true; JsvObjectIterator it; jsvObjectIteratorNew(&it, var); while (lastIndex+1<length && numeric && !jspIsInterrupted()) { JsVar *key = jsvObjectIteratorGetKey(&it); if (!jsvObjectIteratorHasValue(&it) || jsvIsNumeric(key)) { JsVarInt index = jsvObjectIteratorHasValue(&it) ? jsvGetInteger(key) : length-1; JsVar *item = jsvObjectIteratorGetValue(&it); while (lastIndex < index) { lastIndex++; if (!limited || lastIndex<(JsVarInt)JSON_LIMITED_AMOUNT || lastIndex>=length-(JsVarInt)JSON_LIMITED_AMOUNT) { if (!first) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":","); first = false; if (limited && lastIndex==length-(JsVarInt)JSON_LIMITED_AMOUNT) cbprintf(user_callback, user_data, JSON_LIMIT_TEXT); bool newNeedsNewLine = ((flags&JSON_SOME_NEWLINES) && jsonNeedsNewLine(item)); if (flags&JSON_ALL_NEWLINES) { needNewLine = true; newNeedsNewLine = true; } if (needNewLine || newNeedsNewLine) { jsonNewLine(nflags, whitespace, user_callback, user_data); needNewLine = false; } if (lastIndex == index) jsfGetJSONWithCallback(item, nflags, whitespace, user_callback, user_data); else cbprintf(user_callback, user_data, (flags&JSON_NO_UNDEFINED)?"null":"undefined"); needNewLine = newNeedsNewLine; } } jsvUnLock(item); jsvObjectIteratorNext(&it); } else { numeric = false; } jsvUnLock(key); } // non-numeric - but NOT for standard JSON if ((flags&JSON_PRETTY)) jsfGetJSONForObjectItWithCallback(&it, flags, whitespace, nflags, user_callback, user_data, first); jsvObjectIteratorFree(&it); if (needNewLine) jsonNewLine(flags, whitespace, user_callback, user_data); cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?" ]":"]"); } else if (jsvIsArrayBuffer(var)) { JsvArrayBufferIterator it; bool allZero = true; jsvArrayBufferIteratorNew(&it, var, 0); while (jsvArrayBufferIteratorHasElement(&it)) { if (jsvArrayBufferIteratorGetFloatValue(&it)!=0) allZero = false; jsvArrayBufferIteratorNext(&it); } jsvArrayBufferIteratorFree(&it); bool asArray = flags&JSON_ARRAYBUFFER_AS_ARRAY; if (allZero && !asArray) { cbprintf(user_callback, user_data, "new %s(%d)", jswGetBasicObjectName(var), jsvGetArrayBufferLength(var)); } else { const char *aname = jswGetBasicObjectName(var); /* You can't do `new ArrayBuffer([1,2,3])` so we have to output * `new Uint8Array([1,2,3]).buffer`! */ bool isBasicArrayBuffer = strcmp(aname,"ArrayBuffer")==0; if (isBasicArrayBuffer) { aname="Uint8Array"; } cbprintf(user_callback, user_data, asArray?"[":"new %s([", aname); if (flags&JSON_ALL_NEWLINES) jsonNewLine(nflags, whitespace, user_callback, user_data); size_t length = jsvGetArrayBufferLength(var); bool limited = (flags&JSON_LIMIT) && (length>JSON_LIMIT_AMOUNT); // no newlines needed for array buffers as they only contain simple stuff jsvArrayBufferIteratorNew(&it, var, 0); while (jsvArrayBufferIteratorHasElement(&it) && !jspIsInterrupted()) { if (!limited || it.index<JSON_LIMITED_AMOUNT || it.index>=length-JSON_LIMITED_AMOUNT) { if (it.index>0) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":","); if (flags&JSON_ALL_NEWLINES) jsonNewLine(nflags, whitespace, user_callback, user_data); if (limited && it.index==length-JSON_LIMITED_AMOUNT) cbprintf(user_callback, user_data, JSON_LIMIT_TEXT); JsVar *item = jsvArrayBufferIteratorGetValue(&it); jsfGetJSONWithCallback(item, nflags, whitespace, user_callback, user_data); jsvUnLock(item); } jsvArrayBufferIteratorNext(&it); } if (flags&JSON_ALL_NEWLINES) jsonNewLine(flags, whitespace, user_callback, user_data); jsvArrayBufferIteratorFree(&it); cbprintf(user_callback, user_data, asArray?"]":"])"); if (isBasicArrayBuffer && !asArray) cbprintf(user_callback, user_data, ".buffer"); } } else if (jsvIsObject(var)) { IOEventFlags device = (flags & JSON_SHOW_DEVICES) ? jsiGetDeviceFromClass(var) : EV_NONE; if (device!=EV_NONE) { cbprintf(user_callback, user_data, "%s", jshGetDeviceString(device)); } else { bool showContents = true; if (flags & JSON_SHOW_OBJECT_NAMES) { JsVar *proto = jsvObjectGetChild(var, JSPARSE_INHERITS_VAR, 0); if (jsvHasChildren(proto)) { JsVar *constr = jsvObjectGetChild(proto, JSPARSE_CONSTRUCTOR_VAR, 0); if (constr) { JsVar *p = jsvGetIndexOf(execInfo.root, constr, true); if (p) cbprintf(user_callback, user_data, "%v: ", p); jsvUnLock2(p,constr); /* We had the constructor - now if there was a non-default toString function * we'll execute it and print the result */ JsVar *toStringFn = jspGetNamedField(var, "toString", false); if (toStringFn && toStringFn->varData.native.ptr != (void (*)(void))jswrap_object_toString) { // Function found and it's not the default one - execute it JsVar *result = jspExecuteFunction(toStringFn,var,0,0); cbprintf(user_callback, user_data, "%v", result); jsvUnLock(result); showContents = false; // we already printed something } jsvUnLock(toStringFn); } } jsvUnLock(proto); } if (showContents) { JsvObjectIterator it; jsvObjectIteratorNew(&it, var); cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"{ ":"{"); bool needNewLine = jsfGetJSONForObjectItWithCallback(&it, flags, whitespace, nflags, user_callback, user_data, true); jsvObjectIteratorFree(&it); if (needNewLine) jsonNewLine(flags, whitespace, user_callback, user_data); cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?" }":"}"); } } } else if (jsvIsFunction(var)) { if (flags & JSON_IGNORE_FUNCTIONS) { cbprintf(user_callback, user_data, "undefined"); } else { cbprintf(user_callback, user_data, "function "); jsfGetJSONForFunctionWithCallback(var, nflags, user_callback, user_data); } } else if (jsvIsString(var) && !jsvIsName(var)) { if ((flags&JSON_LIMIT) && jsvGetStringLength(var)>JSON_LIMIT_STRING_AMOUNT) { // if the string is too big, split it and put dots in the middle JsVar *var1 = jsvNewFromStringVar(var, 0, JSON_LIMITED_STRING_AMOUNT); JsVar *var2 = jsvNewFromStringVar(var, jsvGetStringLength(var)-JSON_LIMITED_STRING_AMOUNT, JSON_LIMITED_STRING_AMOUNT); cbprintf(user_callback, user_data, "%q%s%q", var1, JSON_LIMIT_TEXT, var2); jsvUnLock2(var1, var2); } else { cbprintf(user_callback, user_data, "%q", var); } } else { cbprintf(user_callback, user_data, "%v", var); } var->flags &= ~JSV_IS_RECURSING; } }
/* This is like jsfGetJSONWithCallback, but handles ONLY functions (and does not print the initial 'function' text) */ void jsfGetJSONForFunctionWithCallback(JsVar *var, JSONFlags flags, vcbprintf_callback user_callback, void *user_data) { assert(jsvIsFunction(var)); JsVar *codeVar = 0; // TODO: this should really be in jsvAsString JsvObjectIterator it; jsvObjectIteratorNew(&it, var); bool firstParm = true; cbprintf(user_callback, user_data, "("); while (jsvObjectIteratorHasValue(&it)) { JsVar *child = jsvObjectIteratorGetKey(&it); if (jsvIsFunctionParameter(child)) { if (firstParm) firstParm=false; else cbprintf(user_callback, user_data, ","); JsVar *name = jsvNewFromStringVar(child, 1, JSVAPPENDSTRINGVAR_MAXLENGTH); cbprintf(user_callback, user_data, "%v", name); jsvUnLock(name); } else if (jsvIsString(child) && jsvIsStringEqual(child, JSPARSE_FUNCTION_CODE_NAME)) { codeVar = jsvObjectIteratorGetValue(&it); } jsvUnLock(child); jsvObjectIteratorNext(&it); } jsvObjectIteratorFree(&it); cbprintf(user_callback, user_data, ") "); if (jsvIsNative(var)) { cbprintf(user_callback, user_data, "{ [native code] }"); } else { if (codeVar) { if (flags & JSON_LIMIT) { cbprintf(user_callback, user_data, "{%s}", JSON_LIMIT_TEXT); } else { bool hasNewLine = jsvGetStringIndexOf(codeVar,'\n')>=0; user_callback(hasNewLine?"{\n ":"{", user_data); if (jsvIsFunctionReturn(var)) user_callback("return ", user_data); // reconstruct the tokenised output into something more readable char buf[32]; unsigned char lastch = 0; JsvStringIterator it; jsvStringIteratorNew(&it, codeVar, 0); while (jsvStringIteratorHasChar(&it)) { unsigned char ch = (unsigned char)jsvStringIteratorGetChar(&it); if (jslNeedSpaceBetween(lastch, ch)) user_callback(" ", user_data); jslFunctionCharAsString(ch, buf, sizeof(buf)); user_callback(buf, user_data); jsvStringIteratorNext(&it); lastch = ch; } jsvStringIteratorFree(&it); user_callback(hasNewLine?"\n}":"}", user_data); } } else cbprintf(user_callback, user_data, "{}"); } jsvUnLock(codeVar); }
void jsfGetJSONWithCallback(JsVar *var, JSONFlags flags, vcbprintf_callback user_callback, void *user_data) { JSONFlags nflags = flags + JSON_INDENT; // if we add a newline, make sure we indent any subsequent JSON more if (jsvIsUndefined(var)) { cbprintf(user_callback, user_data, "undefined"); } else { // Use IS_RECURSING flag to stop recursion if (var->flags & JSV_IS_RECURSING) { cbprintf(user_callback, user_data, " ... "); return; } var->flags |= JSV_IS_RECURSING; if (jsvIsArray(var)) { size_t length = (size_t)jsvGetArrayLength(var); bool limited = (flags&JSON_LIMIT) && (length>JSON_LIMIT_AMOUNT); bool needNewLine = false; size_t i; cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"[ ":"["); for (i=0;i<length && !jspIsInterrupted();i++) { if (!limited || i<JSON_LIMITED_AMOUNT || i>=length-JSON_LIMITED_AMOUNT) { if (i>0) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":","); if (limited && i==length-JSON_LIMITED_AMOUNT) { if (needNewLine) jsonNewLine(nflags, user_callback, user_data); cbprintf(user_callback, user_data, JSON_LIMIT_TEXT); } JsVar *item = jsvGetArrayItem(var, (JsVarInt)i); if (jsvIsUndefined(item) && (flags&JSON_NO_UNDEFINED)) item = jsvNewWithFlags(JSV_NULL); bool newNeedsNewLine = (flags&JSON_NEWLINES) && jsonNeedsNewLine(item); if (needNewLine || newNeedsNewLine) { jsonNewLine(nflags, user_callback, user_data); needNewLine = false; } jsfGetJSONWithCallback(item, nflags, user_callback, user_data); needNewLine = newNeedsNewLine; jsvUnLock(item); } } if (needNewLine) jsonNewLine(flags, user_callback, user_data); cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?" ]":"]"); } else if (jsvIsArrayBuffer(var)) { JsvArrayBufferIterator it; bool allZero = true; jsvArrayBufferIteratorNew(&it, var, 0); while (jsvArrayBufferIteratorHasElement(&it)) { if (jsvArrayBufferIteratorGetFloatValue(&it)!=0) allZero = false; jsvArrayBufferIteratorNext(&it); } jsvArrayBufferIteratorFree(&it); if (allZero) { cbprintf(user_callback, user_data, "new %s(%d)", jswGetBasicObjectName(var), jsvGetArrayBufferLength(var)); } else { cbprintf(user_callback, user_data, "new %s([", jswGetBasicObjectName(var)); size_t length = jsvGetArrayBufferLength(var); bool limited = (flags&JSON_LIMIT) && (length>JSON_LIMIT_AMOUNT); // no newlines needed for array buffers as they only contain simple stuff jsvArrayBufferIteratorNew(&it, var, 0); while (jsvArrayBufferIteratorHasElement(&it) && !jspIsInterrupted()) { if (!limited || it.index<JSON_LIMITED_AMOUNT || it.index>=length-JSON_LIMITED_AMOUNT) { if (it.index>0) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":","); if (limited && it.index==length-JSON_LIMITED_AMOUNT) cbprintf(user_callback, user_data, JSON_LIMIT_TEXT); JsVar *item = jsvArrayBufferIteratorGetValue(&it); jsfGetJSONWithCallback(item, nflags, user_callback, user_data); jsvUnLock(item); } jsvArrayBufferIteratorNext(&it); } jsvArrayBufferIteratorFree(&it); cbprintf(user_callback, user_data, "])"); } } else if (jsvIsObject(var)) { IOEventFlags device = (flags & JSON_SHOW_DEVICES) ? jsiGetDeviceFromClass(var) : EV_NONE; if (device!=EV_NONE) { cbprintf(user_callback, user_data, "%s", jshGetDeviceString(device)); } else { bool first = true; bool needNewLine = false; size_t sinceNewLine = 0; JsvObjectIterator it; jsvObjectIteratorNew(&it, var); cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"{ ":"{"); while (jsvObjectIteratorHasValue(&it) && !jspIsInterrupted()) { JsVar *index = jsvObjectIteratorGetKey(&it); JsVar *item = jsvObjectIteratorGetValue(&it); bool hidden = jsvIsInternalObjectKey(index) || ((flags & JSON_IGNORE_FUNCTIONS) && jsvIsFunction(item)) || ((flags&JSON_NO_UNDEFINED) && jsvIsUndefined(item)); if (!hidden) { sinceNewLine++; if (!first) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":","); bool newNeedsNewLine = (flags&JSON_NEWLINES) && jsonNeedsNewLine(item); if ((flags&JSON_NEWLINES) && sinceNewLine>JSON_ITEMS_ON_LINE_OBJECT) needNewLine = true; if (needNewLine || newNeedsNewLine) { jsonNewLine(nflags, user_callback, user_data); needNewLine = false; sinceNewLine = 0; } cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"%q: ":"%q:", index); if (first) first = false; jsfGetJSONWithCallback(item, nflags, user_callback, user_data); needNewLine = newNeedsNewLine; } jsvUnLock(index); jsvUnLock(item); jsvObjectIteratorNext(&it); } jsvObjectIteratorFree(&it); if (needNewLine) jsonNewLine(flags, user_callback, user_data); cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?" }":"}"); } } else if (jsvIsFunction(var)) { if (flags & JSON_IGNORE_FUNCTIONS) { cbprintf(user_callback, user_data, "undefined"); } else { cbprintf(user_callback, user_data, "function "); jsfGetJSONForFunctionWithCallback(var, nflags, user_callback, user_data); } } else if (jsvIsString(var) && !jsvIsName(var)) { if ((flags&JSON_LIMIT) && jsvGetStringLength(var)>JSON_LIMIT_STRING_AMOUNT) { // if the string is too big, split it and put dots in the middle JsVar *var1 = jsvNewFromStringVar(var, 0, JSON_LIMITED_STRING_AMOUNT); JsVar *var2 = jsvNewFromStringVar(var, jsvGetStringLength(var)-JSON_LIMITED_STRING_AMOUNT, JSON_LIMITED_STRING_AMOUNT); cbprintf(user_callback, user_data, "%q%s%q", var1, JSON_LIMIT_TEXT, var2); jsvUnLock(var1); jsvUnLock(var2); } else { cbprintf(user_callback, user_data, "%q", var); } } else { cbprintf(user_callback, user_data, "%v", var); } var->flags &= ~JSV_IS_RECURSING; } }
void jslPrintPosition(vcbprintf_callback user_callback, void *user_data, struct JsLex *lex, size_t tokenPos) { size_t line,col; jsvGetLineAndCol(lex->sourceVar, tokenPos, &line, &col); cbprintf(user_callback, user_data, "line %d col %d\n",line,col); }