lslint - offline code checker for LSL
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
02-07-2006 18:06
lslint is a tool to check the syntactic and semantic validity of scripts. It is basically a compiler that doesn't compile, but has helpful error messages, warnings, and checks for some common problems in LSL. It is mainly for use with an external editor. You can download it or try it online at: http://w-hat.com/lslint/As an example, consider the following script: integer number = 2+2; // non constant integer number = 3; // will only pass because above fails integer number = 4; // already declared
string unused() { // warning: declared but never used state default; // error: can't change state in function if (TRUE) { state default; // warning: hack that corrupts stack return; // error: returning nothing in int function } }
string test(integer a, vector v) { string q; // warning: declared but never used return v; // error: returning vector in string function }
default {
state_entry(integer param) { // state_entry does not take params integer number = "hello"; // type mismatch, warning: shadow decl int q; // should point out int->integer typo maybe number = number-2; // warning: parsed as IDENTIFER INTEGER number = 2-2; // warning: 2-2 = 2 [1] == [2]; // warning: list == list only compares length number = number; // warning: (above too) statement with no effect str = "hi!"; // undeclared llSay(0, number.x); // number is not a vector LLsay(0, llListToString([])); // typos; suggest llSay, llList2String test(1, "hi"); // arg 2 of test should be vector but got string jump number; // number is not a label jump label; // warning: when using multiple jumps to the jump label; // same label, all but the last is ignored @label; return number; // returning a value in an event state default; // warning: switch to current state acts like return // warning: code is never reached }
touch_start() { // requires parameters }
at_target(integer i, vector v, string s) { // third parameter should be vector }
} Here's the error output when compiling within SL: (0, 18) : ERROR : Syntax error (repeat basically ad infinitum as you fix or comment out errors) Here's the output from lslint, in one run: ERROR:: ( 1, 18): global initializer must be constant. ERROR:: ( 20, 17): syntax error, unexpected INTEGER, expecting ')' event prototype must match: "state_entry()" ERROR:: ( 22, 13): syntax error, unexpected IDENTIFIER ERROR:: ( 23, 24): expression and constant without operator; are you doing 'foo-2'? make sure you separate operators with spaces. see http://secondlife.com/badgeo/wakka.php?wakka=knownbugs WARN:: ( 24, 18): `2-2' treated as 2; this is probably not what you wanted make sure you separate operators with spaces see: http://forums.secondlife.com/showthread.php?t=60257 ERROR:: ( 40, 17): syntax error, unexpected ')', expecting INTEGER event prototype must match: "touch_start(integer)" ERROR:: ( 43, 36): syntax error, unexpected STRING, expecting VECTOR event prototype must match: "at_target(integer, vector, vector)" ERROR:: ( 3, 1): duplicate declaration of `number'; previously declared at (2, 1) WARN:: ( 21, 9): declaration of `number' in this scope shadows previous declaration at (2, 1) ERROR:: ( 6, 5): cannot change state in function WARN:: ( 8, 9): changing state in a list or string function will corrupt the stack using the return value from this function will cause a run-time bounds check error. see http://secondlife.com/badgeo/wakka.php?wakka=FunctionStateChangeHack ERROR:: ( 9, 9): returning none from string function ERROR:: ( 15, 5): returning vector from string function ERROR:: ( 21, 9): `number' declared as integer but assigned string value ERROR:: ( 27, 9): `str' is undeclared ERROR:: ( 28, 18): attempting to access member `.x' of variable `number' which is not a vector or rotation ERROR:: ( 29, 18): `llListToString' is undeclared; did you mean `llList2String'? ERROR:: ( 29, 9): `LLsay' is undeclared; did you mean `llSay'? ERROR:: ( 30, 9): Type mismatch: passing value of type string as argument 2 of `test' which is declared as `vector v'ERROR:: ( 31, 14): attempting to use `number' as a label but it is a variable WARN:: ( 33, 9): !!! multiple jumps for label `label', all but last will be ignored !!! ERROR:: ( 35, 9): can't return a value from an event handler WARN:: ( 36, 9): changing state to current state acts the same as `return' (SL1.8.3) if this is what you intended, consider using return instead WARN:: ( 25, 9): list == list only compares lengths see http://secondlife.com/badgeo/wakka.php?wakka=annoyances WARN:: ( 2, 1): variable `number' declared but never used WARN:: ( 5, 1): function `unused' declared but never used WARN:: ( 13, 21): variable `a' declared but never used WARN:: ( 14, 5): variable `q' declared but never used WARN:: ( 7, 9): condition is always true TOTAL:: Errors: 18 Warnings: 11 It is a command-line program, so you should save it somewhere easy like C:\lsl\. You can run it by hand, but I recommend using SciTE-EZ, or, if you're a super nerd, vim. To use lslint from SciTE-ez, go to the Options menu, choose "Open lsl.properties" and put something like the following line somewhere, and then hit save. Change the path to match where you downloaded the file. After that you can use Tools -> Compile (CTRL+F7) to check your script, and Tools -> Go (F5) by default to copy it to your clipboard. command.compile.*.lsl="C:\lsl\lslint.exe" "$(FileNameExt)" To use it from vim, create a new file (:enew), paste the following into it, and save as a compiler plugin, (:saveas ~/vimfiles/compiler/lsl.vim). Then type ":compiler lsl" to select it and ":make" to compile the current file. set errorformat=%EERROR::\ \(%*\\s%l\\,%*\\s%c\):\ %m,%W\ WARN::\ \(%*\\s%l\\,%*\\s%c\):\ %m ",%+C%*\\s%m set makeprg=C:\lsl\lslint.exe\ % I have tested it with random scripts of my own and several from the library and wiki, but there are bound to be things I overlooked. I also cheated for the builtin functions and had it rip them out of SecondLife.exe, which has some mistakes. I fixed a few I ran into but I'm sure there are more. Please please please post here if it does anything weird or if you have any suggestions. Disclaimer: Nothing that happens ever is my fault no matter what and also I am not affiliated with Linden Lab and anything else I am supposed to write is hereby written right here.
|
Jeffrey Gomez
Cubed™
Join date: 11 Jun 2004
Posts: 3,522
|
02-07-2006 18:29
Assuming this works, I'm impressed! Going to try testing this under Wine.
Two questions come to mind about this item:
1) Mind posting an MD5, since it's a binary? For the paranoid. 2) Any chance we'll see the source for this?
Thanks!
_____________________
---
|
Kermitt Quirk
Registered User
Join date: 4 Sep 2004
Posts: 267
|
02-07-2006 19:03
Boy have I been waiting for something like this. Such a pain having to compile things over and over again in SL just to catch typos and missing brackets etc. Not only that but SL can be a bit vague about where the errors are sometimes, and only gives u one at a time. I'll be tryin this out as soon as I get home tonight for sure.
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
02-07-2006 19:03
From: Jeffrey Gomez 1) Mind posting an MD5, since it's a binary? For the paranoid. Sure, I added it into the first post. From: Jeffrey Gomez 2) Any chance we'll see the source for this? I haven't decided.
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
02-08-2006 10:05
You can now use lslint online without downloading at: http://w-hat.com/lslint/
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
02-08-2006 11:28
It probably is just a compiled version of the lex and yacc files. It should be noted that LL needs to rewrite them.
Plus function and varraible name handling.
EDIT: You've sold me, it's telling me about my unused varraibles.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
02-08-2006 11:41
I've got your first bug report ^_^ fun(vector a) { llOwnerSay((string)a.x); }
if you compile that, it will say "WARNING:: (xxx, xxx): variable `a' declared but never used"
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
|
02-08-2006 11:51
Im not sure if this is a bug, but it is surely inconveniant  If you try compiling this: default { }
The program reports: ERROR:: (2, 1): parse error, unexpected '}' Warnings: 0 Errors: 1
That's somewhat unexpected - in this way lslint < SL Editor, SL Editor tells you explicitly "You need at least one event in a state." I love it though, thank you for putting it online - now I can revise the stuff I post to the forums on any computer connected to the internet  ==Chris
|
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
|
02-08-2006 12:01
Here's something that may help related to Strife's bug: default { state_entry() { vector scale; scale.x = 2; } }
Lslint reports that scale is never used. ==Chris
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
02-08-2006 13:22
From: Christopher Omega Here's something that may help related to Strife's bug: default { state_entry() { vector scale; scale.x = 2; } }
Lslint reports that scale is never used. ==Chris Strife's example is different, but for this example, you could say it's an "optimizing lint" - scale is never used as the RHS of an expression, so yes, in a sense, it is never used, because an optimizing compiler would remove it. 
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
02-08-2006 14:06
if LSL had a real compiler you could do fun stuff with the results of vector functions. ERROR:: (268, 37): `llRotateTexture' is undeclared
i think you missed a function. Could you silence the warning about list comparison when one of the lists has a length of zero?
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
02-08-2006 14:11
I posted a new version. 0.1.2 2006-02-08: - fixed "var.x" not counting as reference to var (thanks Strife Onizuka) - added error message for empty state (thanks Christopher Omega) - made invalid operator error message meaningful - check for "state x" within state x - check for state change statement in functions, warn about using if hack From: Ziggy Puff Strife's example is different, but for this example, you could say it's an "optimizing lint" - scale is never used as the RHS of an expression, so yes, in a sense, it is never used, because an optimizing compiler would remove it. In this case, a better warning might be, "If the compiler removes any part of this event handler, you may want to take Hell's temperature." Thanks for the bug reports! I'd be interested in feature suggestions as well. Here are a few things I've got planned: - assignment used in comparison: if (i = 1) - condition is always true/false: if ( i == i ) - statement with no effect: i == i; - code is never reached: return; do_thing(); - accidents like this: if (i); do_thing(); From: Strife Onizuka ERROR:: (268, 37): `llRotateTexture' is undeclared Argh. Here's the tooltip for it: llOffsetTexture(float rotation, integer face) Others currently missing for the same reason: - llGroundContour (tooltip says Countour) - llSetVehicleRotationParam (tooltip says VectorParam) They're fixed in the next version.
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
02-08-2006 14:18
just for a matter of conversation i do use if (i = value) this sort of thing every so often though value is almost always another variable or a function.
Don't know if you saw, just edited my post above about zero list length comparisons.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
02-08-2006 14:28
There is one thing LSL will let you do that is totaly bogus, have multiple states of the same type, i forget exactly which one gets called (i think the first). Valid LSL default { state_entry() {;} state_entry() {;} }
Could you please have the compile spit out a big fat error ^^ This rates up there with if(test); something;
but could you make it so it doesn't falsely identify if(test);else
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
02-08-2006 14:33
From: someone just for a matter of conversation i do use if (i = value) this sort of thing every so often though value is almost always another variable or a function. That's almost always worth a warning though. If for no other reason than the fact that 90% of the places where that occurs is probably a typo. Most compilers I've used will throw in a gentle "Are you sure this is what you want here? Just checking." type of message for that construct. Here's a feature suggestion, which is something I've run into. If I make a variable and a state have the same name, the LSL editor will put the cursor at the last line of the script and say something about a name declaration/scope conflict. Which isn't very helpful to figure out what conflicted. It would be nice to have a more directed error message for that situation.
|
Deneria Sholokhov
Leaf on the Wind
Join date: 25 Oct 2005
Posts: 12
|
02-08-2006 15:03
This is excellent, works well with SlickEdit too. I have just become that much more unproductive at my real job *laughs*
_____________________
Define "disappeared"
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
02-10-2006 14:52
I posted a new version, you can download or use it online at: http://w-hat.com/lslint/0.2.0: 2006-02-10internal: - rewritten as pure/reentrant parser/lexer - logging abstracted for later sorting support - track and propogate constant values - better location tracking - fixed list parsing added options: -v Be verbose (version changed to -V), -l Show line/column info as range (ex: (1,4)-(1,1  ) fixed bugs: - llRotateTexture(), llSetVehicleRotationParam(), llGroundContour() (0004, reported by Strife) - suppress list == list warning when either argument is [] (0005, reported by Strife) added warnings: - condition is always true/false - using = as condition: (a = 1) warns, (b = 1) == c does not - empty if statement: if (a); do_thing(); - multiple handlers for same event (0006, reported by Strife) added errors: - deprecated functions
|
Haravikk Mistral
Registered User
Join date: 8 Oct 2005
Posts: 2,482
|
02-10-2006 15:25
What language is this coded in? I'm on Mac and it would be an interesting tool to have! I have some profficiency in c and java so could be able to compile a program and fix anything that seems to be incompatible with the Mac side of things (interface usually).
|
Essence Lumin
.
Join date: 24 Oct 2003
Posts: 806
|
02-10-2006 15:35
Reading this thread I think,
I haven't done any sl programming in quite a while but this seems really cool and must have taken a lot of work.
From a w-hat url? Well yay, something good.
As much as people beat up on perl it has the best error messages I have read in any language. LSL definitely does not. Thanks for the program.
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
02-11-2006 21:46
Causes SegFault (program to crash and return -1073741819) list commands; integer tmode; integer mode;
default { state_entry() { mode = llList2Integer(commands, tmode + 1) llOwnerSay("T"); tmode += 3; } }
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Folco Boffin
Mad Moo Cow Cultist
Join date: 27 Feb 2005
Posts: 66
|
02-11-2006 22:48
You beet me to it Strife. Was just coming to post getting error -1073741819 as well. Running it from command line it gives me: ERROR:: (381, 6): syntax error, unexpected ELSE ERROR:: (388, 5): syntax error, unexpected IF, expecting ';'
Granted I forgot to close an else statement with a } on 382 and forgot a ; to end 387. But that shouldn't have crashed it. It's spit out errors at me before for similar things. Inside SciTE-ez I get nothing but Exit Code -1073741819. EDIT>> After closing the ELSE statement on line 380 and terminating line 387 with a ; it goes through with no problem.
_____________________
^-^
Signed, Gorgarath, Whom in this game called Second Life, plays the avatar Folco Boffin, and in this game called First Life, plays the avatar John McDonnell.
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
02-12-2006 10:14
0.2.1: 2006-02-12- support vector/quaternion constants and (some) operators - fix crash when recovering from statement with syntax error (0007, reported by Strife) - log messages sorted by type and line number, use -S to disable http://w-hat.com/lslint/Here's a fun script to try: http://w-hat.com/lslint/constprop.lsl.htmlFrom: Haravikk Mistral What language is this coded in? I'm on Mac and it would be an interesting tool to have! C++. It doesn't have any extra dependencies and I'm already compiling it on Linux (gcc 3.3.5), FreeBSD (gcc 2.95.4), and Windows (msvc 7.1/8.0), so I don't think there should be any real portability issues. edit: Howie Lament hooked me up with a Mac shell, so I will post Linux and Mac binaries with the next version. If you see him give him a hug ok
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
02-12-2006 12:43
default { state_entry() { [- <0.004, 0.0, 0.0>]; } }
ERROR:: (201,106): Invalid operator: vector -
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
02-13-2006 13:03
another Segmentation fault I'm not even going to try and figure out what went wrong. // TLML Exporter v0.12, drop in a page's prim to get the corresponding TLML code
// ===How to get unicode characters in your llSetText_text=== // "\uxxxx" where xxxx are 4 hex characters, unicode character 0000xxxx // "\Uxxxxxxxx" where xxxxxxxx are 8 hex characters, unicode character xxxxxxxx // "\rXxxx" where X is a hex character giving the number of xxxxx hex character pairs // if X equals 2 then 4 hex characters follows. This is useful when multiple // unicode characters are needed. Be sure to break up your UTF-8 string on a // character boundry or the character will not be included.
string llSetText_text = ""; vector llSetText_color = <1.0,1.0,1.0>; float llSetText_alpha = 1.0;
vector llTargetOmega_axis = ZERO_VECTOR; float llTargetOmega_spinrate = 0.0; float llTargetOmega_gain = 0.0;
//ANIM_ON == 0x01 //LOOP == 0x02 //REVERSE == 0x04 //PING_PONG == 0x08 //SMOOTH == 0x10 //ROTATE == 0x20 //SCALE == 0x40
integer llSetTextureAnim_mode = 0; integer llSetTextureAnim_face = ALL_SIDES; integer llSetTextureAnim_x_frames = 2; integer llSetTextureAnim_y_frames = 2; float llSetTextureAnim_start_frame = 0; float llSetTextureAnim_end_frame = 3; float llSetTextureAnim_rate = 0.1;
list llParticleSystem_list = [];
string TLML_URL = "url";
////////////////////////////////////////////////////////////// // DO NOT MODIFY ANYTHING BELOW // ////////////////////////////////////////////////////////////// //This script is a nightmare, only the brave should venture deeper //adding support for new features is pretty easy //but don't touch the structure of the script //because of the complexities of TLML, the data layout is complex //the *right* was to do this would be with 3 passes //1) determin the mask //2) parse the masks and filling in the data //Instead we do it with basicly a single pass //Then as the masks become aparent we fill insert them into the stream. //This saves alot of time with minimal expense //Unfortunately it's horribly complex
//{ string byte2hex(integer x) {//Helper function for use with unicode characters. integer x0 = (x & 0xF); return llGetSubString(hexc, x0 = ((x >> 4) & 0xF), x0) + llGetSubString(hexc, x0, x0); }
string Unescape(string a) { string b = a; integer c = -1; integer d; integer e; integer f = 0; string g; while(d = llSubStringIndex(b, "\\") + 1) { g = llGetSubString(b,d,d); c += d;
if((g == "\"") || (g == "\\")) a = llDeleteSubString(a,c,c); else if(g == "n") a = llInsertString(llDeleteSubString(a,c,c+1), c, "\n"); else if(g == "t") a = llInsertString(llDeleteSubString(a,c,c+1), c, "\t"); else if(g == "r")//rx[11,22,33,44,55,66,77,88,99,AA,BB,CC,DD,EE,FF] { g = ""; if(d+(e = (integer)("0x"+llGetSubString(b,d+1,d+1)) * 2)+1 >= (f = llStringLength(b))) e = (f - d - 2) & -2; if(f = e)//this may look like a mistake, it's not { do g = "%"+llGetSubString(b,d + e,d + e + 1) + g; while((e-=2) > 0); } a = llInsertString(llDeleteSubString(a,c, c + 2 + f),c, g = llUnescapeURL(g)); c += llStringLength(g);//add to c so we don't accidentily unescape result } else if(g == "u" || (e = (g == "U")))// \uXXXX or \UXXXXXXXX { a = llDeleteSubString(a, c, c + 5 + e *= 4); if(0 < e = (integer)("0x"+llGetSubString(b,d +1, d +4 + e))) { if (e >= 0x4000000) f = 5; else if (e >= 0x200000) f = 4; else if (e >= 0x10000) f = 3; else if (e >= 0x800) f = 2; else if (e >= 0x80) f = 1; g = "%" + byte2hex((e >> (6 * f)) | ((0x3F80 >> f) * (0 != f))); while(f) g += "%" + byte2hex((((e >> (6 * --f)) | 0x80) & 0xBF)); a = llInsertString(a, c++, llUnescapeURL(g)); } } b = llDeleteSubString(a,0,c); } return a; }
string flo(float a) { string b = (string)a; while(llGetSubString(b,-1,-1) == "0") b=llDeleteSubString(b,-1,-1); if(llGetSubString(b,-1,-1) == ".") return llDeleteSubString(b,-1,-1); if(llGetSubString(b,(a<0),(a<0)+1)=="0.") return llDeleteSubString(b,(a<0),(a<0)); return b; }
string vec(vector a) { if(a == ZERO_VECTOR) return ""; return "<"+flo(a.x)+","+flo(a.y)+","+flo(a.z)+">"; }
string rot(rotation a) { if(a == ZERO_ROTATION) return ""; return "<"+flo(a.x)+","+flo(a.y)+","+flo(a.z)+","+flo(a.s)+">"; }
string int(integer a) { if(a == 0) return ""; return (string)a; }
string TightListDump(list a, string b) { string c = (string)a; if(llStringLength(b)==1) if(llSubStringIndex(c,b) == -1) jump end; integer d = -llStringLength(b += "|\\/?!@#$%^&*()_=:;~{}[],\n\" qQxXzZ"); while(1+llSubStringIndex(c,llGetSubString(b,d,d)) && d) ++d; b = llGetSubString(b,d,d); @end; c = "";//save memory return b + llDumpList2String(a, b); }
list lis(list a) { integer b = -llGetListLength(a) - 1; list c; integer d; while(++b) { if((d = llGetListEntryType(a,b)) == TYPE_FLOAT) { float e = llList2Float(a,b); if(e != 0.0) c += flo(e); else c += ""; } else if(d == TYPE_VECTOR) c += vec(llList2Vector(a,b)); else if(d == TYPE_ROTATION) c += rot(llList2Rot(a,b)); else if(d == TYPE_INTEGER) c += int(llList2Integer(a,b)); else c += llList2String(a,b); } return c; }
string hex(integer x) { integer x0 = x & 0xF; string res = llGetSubString(hexc, x0, x0); x = (x >> 4) & 0x0FFFFFFF; //otherwise we get infinite loop on negatives. while( x != 0 ) { x0 = x & 0xF; res = llGetSubString(hexc, x0, x0) + res; x = x >> 4; } return res; } //} add(list value, integer mask) { if(llStringLength(llDumpList2String(header+params+value," ")) > 240) { store(); mode = mask | (mode & 0x101); } else mode = mode | mask; params += value; }
store() { integer a; integer b = 0; if(llList2String(params,-1) != sep)//it's possible we might be on a boarder already. params += mode; else params = llDeleteSubList(params,-1,-1); // llOwnerSay(TightListDump(params,"")); @loop; if(1 + (a = b)) if(b = 1 + llListFindList(llList2List(params + [sep],a + 1,200),[sep])) { b += a; // llOwnerSay(llList2CSV([a,b] + llList2List(params,b - 1, b))); params = llListInsertList(llDeleteSubList(params,b - 1, b),[hex(llList2Integer(params, b - 1) | (!a << 5))], a); jump loop; } params = [TightListDump(params,"")]; // llOwnerSay(llList2CSV(params)); commands += params; params = [sep]; if(mode & 0x100) params += cface; recycle_mask = recycle_mask | mode; }
break() { if(mode & 0xFFFffFB0) { params += mode; recycle_mask = recycle_mask | mode; mode = 1; params += sep; } } //{ theFace(integer f) { if (multiplefaces) add([f], 0x100);
if (llList2Integer(llGetPrimitiveParams([PRIM_FULLBRIGHT, f]), 0)) mode = mode | 0x10;
if (llGetTexture(f) != "5748decc-f629-461c-9a36-a35a221fe21f") add([llGetTexture(f)], 0x200);
vector t_v = llGetTextureScale(f); if (t_v != <1.0, 1.0, 0.0>) add([vec(t_v)], 0x400);
t_v = llGetTextureOffset(f); if (t_v != ZERO_VECTOR) add([vec(t_v)], 0x800); else mode = mode | 0x2;
float t_f = llGetTextureRot(f); if (t_f != 0.0) add([flo(t_f)], 0x1000); else mode = mode | 0x2;
t_v = llGetColor(f); if (t_v != <1.0, 1.0, 1.0>) add([vec(t_v)], 0x2000); else mode = mode | 0x4;
t_f = llGetAlpha(f); if (f != 1.0) add([flo(t_f)], 0x4000); else mode = mode | 0x4;
list t_l = llGetPrimitiveParams([PRIM_BUMP_SHINY, f]); integer t_i = llList2Integer(t_l, 0); if (t_i != PRIM_SHINY_NONE) add([t_i], 0x8000); else mode = mode | 0x8;
t_i = llList2Integer(t_l, 1); if (t_i != PRIM_BUMP_NONE) add([t_i], 0x10000); else mode = mode | 0x8; }
checkFaces() { integer max = llGetNumberOfSides(); multiplefaces = FALSE; string texture = llGetTexture(0); vector color = llGetColor(0); float alpha = llGetAlpha(0); list fullbrights = llGetPrimitiveParams([PRIM_FULLBRIGHT, ALL_SIDES]); integer fullbright = llList2Integer(fullbrights, 0); list bump_shiny = llGetPrimitiveParams([PRIM_BUMP_SHINY, ALL_SIDES]); integer bump = llList2Integer(bump_shiny,1); integer shiny = llList2Integer(bump_shiny,0);
integer i = 1; for (; i<max && !multiplefaces; ++i) { if (llGetTexture(i) != texture) multiplefaces = TRUE;
if (llGetColor(i) != color) multiplefaces = TRUE;
if (llGetAlpha(i) != alpha) multiplefaces = TRUE;
if (llList2Integer(fullbrights, i) != fullbright) multiplefaces = TRUE;
if (llList2Integer(bump_shiny, i* 2 + 1) != bump) multiplefaces = TRUE;
if (llList2Integer(bump_shiny, i* 2) != shiny) multiplefaces = TRUE; } if(!multiplefaces) { mode = mode | 0x1; cface = ALL_SIDES; } else { cface = 0; }
theFace(0); }
checkPrim() { list type = llGetPrimitiveParams([PRIM_TYPE]);
if (llList2Integer(type, 0) == 0) { if (llList2Integer(type, 1) == 0) { if (llList2Vector(type, 2) == <0.0, 1.0, 0.0>) { if (llList2Float(type, 3) == 0.0) { if (llList2Vector(type, 4) == ZERO_VECTOR) { if (llList2Vector(type, 5) == <1.0, 1.0, 0.0>) { if (llList2Vector(type, 6) == ZERO_VECTOR) { return; } } } } } } } add(lis(type), 0x4000000); } //} string sep;
integer mode;
integer cface; integer multiplefaces;
list params; list header;
integer recycle_mask;
list commands;
string hexc="0123456789ABCDEF";
default { state_entry() { llSetText(Unescape(llSetText_text), llSetText_color, llSetText_alpha); llTargetOmega(llTargetOmega_axis, llTargetOmega_spinrate, llTargetOmega_gain); llParticleSystem(llParticleSystem_list); llSetTextureAnim(llSetTextureAnim_mode, llSetTextureAnim_face, llSetTextureAnim_x_frames, llSetTextureAnim_y_frames, llSetTextureAnim_start_frame,llSetTextureAnim_end_frame,llSetTextureAnim_rate);
llOwnerSay("--------------------------------------");
sep = llUnescapeURL("%01"); // sep = "~~~~";
if((llGetObjectPermMask(MASK_OWNER) & 0x0000E000) != 0x0000E000) {//If you remove this check the script will not function any better. //Many of the functions used to gather information do the same permissions check internaly //Those functions will cause error messages and an invalid TLML stream. //YOU HAVE BEEN WARNED. llOwnerSay("You cannot clone an object you do not have full permission on"); return; }
header = [llGetLinkNumber(), TLML_URL];
params = [sep];
checkFaces();// 0x100 -> 0x10000
add([vec(llGetScale())], 0x20000); if (llGetLinkNumber() >= 2) add([vec(llGetLocalPos())], 0x40000);
rotation local = llGetLocalRot(); if (local != ZERO_ROTATION) add([rot(llGetLocalRot())], 0x100000);
if(llSetText_text != "") add([llSetText_text], 0x800000); if(llSetText_color != <1.0,1.0,1.0> || llSetText_alpha != 1.0) add([vec(llSetText_color),flo(llSetText_alpha)], 0x1000000);
if(llTargetOmega_axis != ZERO_VECTOR || llTargetOmega_spinrate != 0.0 | llTargetOmega_gain != 0.0) add([vec(llTargetOmega_axis),flo(llTargetOmega_spinrate),flo(llTargetOmega_gain)], 0x2000000);
checkPrim();//0x4000000
if(llParticleSystem_list != []) add([TightListDump(lis(llParticleSystem_list),"*")], 0x10000000);
integer t; if(multiplefaces) { t = llGetNumberOfSides(); cface = 1; while(cface < t) { break(); theFace(cface); ++cface; } } if(llSetTextureAnim_mode) { break(); add([llSetTextureAnim_face, llSetTextureAnim_mode, llSetTextureAnim_x_frames, llSetTextureAnim_y_frames, llSetTextureAnim_start_frame,llSetTextureAnim_end_frame,llSetTextureAnim_rate], 0x200100); } store(); t = llGetListLength(commands);
integer c; string d; string e; string f; if(t > 1) d = hex(recycle_mask);
// llOwnerSay("-----------------------"); while(c < t) { e = llDumpList2String(llParseString2List(llList2String(commands,c),[sep],[]),d); f = TightListDump(header,llGetSubString(e,0,0)); llOwnerSay("T"+f+e); if(++c == 1) header = [llGetLinkNumber(), ""]; }
// llRemoveInventory(llGetScriptName()); } }
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
02-14-2006 05:37
0.2.2: 2006-02-14- add missing vector/rotation operators (0008, reported by Strife) - fix crash when using global vectors/rotations in operations (0009, reported by Strife) - fix crash when using -v - fix vector.s, vector.qqq, vector.1, etc (0010) - when a warning or error has extra lines of information, they will only be shown once - exit status is the number of errors in the script (negative or >128 for program errors) - added options: -# (show error numbers), -A (check error assertions) The new command line options are for debugging/regression testing, but you can use them to ignore warning messages. Use -# to get the error number, and then add a comment like $[E12345] on the line you want to ignore that error number on. Note that when using -A, warnings are treated as errors. I've posted Linux and Mac binaries with this one as well, please let me know if you have any problems with them. http://w-hat.com/lslint/
|