import com.vitesselearning.coursedesign.utilities.MiscUtility; import com.vitesselearning.coursedesign.engine.VLCourse; import com.vitesselearning.coursedesign.debug.*; class com.vitesselearning.coursedesign.debug.DebuggerOs { private var DECOR:String = "*************************************************************"; private var WELCOME:String = "welcome to CDOS version 1.0.1 written by Apolo Pena"; private var COM:DebuggerOsCommands; public var watchlist:WatchList; public var commandList:Array; public var course:VLCourse; public function DebuggerOs() { COM = new DebuggerOsCommands(); commandList = new Array(); setCommandList(); } public function getInfo():String { var _return:String = DECOR + "\n" + WELCOME + "\n\tThe current list of valid commands is:"; var len:Number = commandList.length; for (var i = 0; i < len; i++) { _return += "\n\t\t"+commandList[i]; } _return +="\nType help 'command' where 'command' is the command you want information about\n"+DECOR; return _return; } public function fetch(key:String):Object { var len:Number = commandList.length; for (var i = 1; i<=len; i++) { if (COM.commands["com"+i].com == key) { return COM.commands["com"+i]; } } return null; } public function isValid(command:String):Boolean { for (var i in commandList) { //Debugger.trace("command= "+command+"::---:: commandList["+i+"]="+commandList[i]); if (commandList[i] == command) { return true; } } return false; } private function setCommandList() { var count:Number = 0; for (var i in COM.commands) { count++; commandList.push(COM.commands["com"+count].com); } } public function help (arg:String):Boolean { var msg:String = "HELP RESULTS:\n"; var isValidCom:Boolean = false; var isOption:Boolean = false; if (arg == "/a") { isOption = true; //isValidCom = true; } else if (isValid(arg)) { isValidCom = true; } if (!isValidCom) { Debugger.showOsError("The argument: "+arg+" is not valid", "help"); return false; } if (isOption) { // TODO: show help on all commands } else { // show the info for the command requested var command:Object = fetch(arg); var commandItems:Array = new Array(); for (var i in command) { commandItems.push(command[i]); } // now slice off the last two items because we don't want to display, the options or the isLocal properties commandItems.pop(); commandItems.pop(); // the second item is the func property, we want to omit this commandItems.splice(1, 1); // create the message var singleComLen:Number = commandItems.length; for (var i = 0; i < singleComLen; i++) { // the first item is the command name but it needs a prefix if ( i < 1) { msg += "Command name: "; } msg += commandItems[i] + "\n"; } Debugger.traceOs(msg); } return true; } public function traceProperty (arg:String):Boolean { // non-local commands like this one need a reference to course if (course == undefined) { course = VLCourse.getInstance(); } var dataType:String; //Debugger.trace("traceNodeSet-->nodeSet.slice(0, 6).toLowerCase() = "+arg.slice(0, 6).toLowerCase()); if (arg.toLowerCase() == "course") { var obj:Object = course; dataType = "object"; } else if (arg.slice(0, 6).toLowerCase() == "course" && arg.length > 6) { //Debugger.trace("traceNodeSet-->nodeSet.slice(7, nodeSet.length)="+arg.slice(7, arg.length)); var obj:Object = course[arg.slice(7, arg.length)]; dataType = typeof(course[arg.slice(7, arg.length)]); } else { var obj:Object = eval(arg); if (obj == undefined) { Debugger.showOsError("the non-course object you wanted to trace: "+arg+" evaluated to undefined. Either it doesn't exist or it is private or static", "trace"); return false; } } if (obj == undefined) { Debugger.showOsError("the object you wanted to trace: "+arg+" evaluated to undefined. Either it doesn't exist or it is private or static", "trace"); return false; } Debugger.traceOs("TRACE RESULTS:\nThe data type of : "+arg+" is "+dataType+" it's value is: "+eval(arg)+" and it's properties (if any) are as follows:"); for (var i in obj) { Debugger.traceOs("\t"+(arg+'.'+i)+"\n\t\tvalue is: "+obj[i]+"\n\t\tdata type is: "+typeof (obj[i])); } } /** Executes a function * */ public function exec(arg:String):Boolean { // non-local commands like this one need a reference to course if (course == undefined) { course = VLCourse.getInstance(); } // the array that will be passed the the funtion var args:Array = new Array(); // declare the function to call, this will be set from an evaluated string later var func:Function; // determine how many arguments we have var argTotal:Number = arg.split(':').length - 1; // TODO: make this smarter so it wont break when passing strings containing argument values with commas and colons in the in them // start parsing - expecting the exact syntax: object.path.function(value2:PrimitiveDataType, value2:PrimitiveDataType, .....) var chunks:Array = arg.split(','); // parse first chunk which will get the function to call and the first argument chunk var functionString:String = chunks[0].slice(0, chunks[0].indexOf('(')); var c1:String = chunks[0]; var c1s1Index:Number = c1.indexOf('('); var c1s1:String = c1.slice(0, c1s1Index); var c1s2:String = new String(); // if this is the only argument then the final character in the string will be a closing parens so omit that or errors will be thrown father down the line if (argTotal < 2) { c1s2 = c1.slice(c1s1Index+1, c1.length - 1); } else { c1s2 = c1.slice(c1s1Index+1, c1.length); } // now parse the first argument chunk var arg1Chunks:Array = c1s2.split(':'); // cast the data if (arg1Chunks[1].toLowerCase() == "number") { // check for an invalid number value if (!isNaN(Number(arg1Chunks[0]))) { var arg1Value = Number(arg1Chunks[0]); } else { Debugger.showOsError("DebuggerOs.exec() failed-->first arg: "+arg1Chunks[0]+" is an invalid number value", "exec"); return false; } } else if (arg1Chunks[1].toLowerCase() == "boolean") { // error handle if (arg1Chunks[0].toLowerCase() == "true" || arg1Chunks[0].toLowerCase() == "false") { var arg1Value = (arg1Chunks[0].toLowerCase() == "true" ? true : false); } else { // output an a fatal error, if we didn't do this invalid values would always be false Debugger.showOsError("DebuggerOs.exec() failed-->first arg: "+arg1Chunks[0]+" is an invalid boolean value", "exec"); return false; } } else if (arg1Chunks[1].toLowerCase() == "string") { var arg1Value = arg1Chunks[0]; } else { Debugger.showOsError("DebuggerOs.exec() failed-->'"+arg1Chunks[1]+"' is an invalid datatype.", "exec"); return false; } args.push(arg1Value); // check again to see if this is the only arg, if it is then finish up here if (argTotal < 2) { func = eval(functionString); // only called defined functions if (func != undefined) { func.apply(null, args); return true; } else { Debugger.showOsError("DebuggerOs.exec() failed-->the function: "+functionString+" could not be located and probably does not exist!"); return false; } } // next parse the last argument, first slice off the closing parenthesesis on the last argument string var lastArg:String = chunks[chunks.length-1].slice(0, chunks[chunks.length-1].length-1); var lastArgChunks:Array = lastArg.split(':'); // cast the data if (lastArgChunks[1].toLowerCase() == "number") { // check for an invalid number value if (!isNaN(Number(lastArgChunks[0]))) { var lastArgValue = Number(lastArgChunks[0]); } else { Debugger.showOsError("DebuggerOs.exec() failed-->last arg: "+lastArgChunks[0]+" is an invalid number value", "exec"); return false; } } else if (lastArgChunks[1].toLowerCase() == "boolean") { // error handle - the value has a space in front of it (because the syntax requires that you put a space afer the comma when delimiting arguments) var lastArgValueString:String = lastArgChunks[0].slice(1, lastArgChunks[0].length); if (lastArgValueString.toLowerCase() == "true" || lastArgValueString.toLowerCase() == "false") { var lastArgValue = (lastArgValueString.toLowerCase() == "true" ? true : false); } else { // output an a fatal error, if we didn't do this invalid values would always be false Debugger.showOsError("DebuggerOs.exec() failed-->last arg: "+lastArgValueString+" is an invalid boolean value", "exec"); return false; } } else if (lastArgChunks[1].toLowerCase() == "string") { var lastArgValue = lastArgChunks[0].slice(1, lastArgChunks[0].length); } else { Debugger.showOsError("DebuggerOs.exec() failed-->'"+lastArgChunks[1]+"' is an invalid datatype.", "exec"); return false; } // the last arg has to be pushed last so don't push it yet // parse the all the argmentes in between the first arguemnt and the last argument var remainingArgumentPairs = new Array(); for (var i = 1; iremaining arg: "+remainingArgumentPairs[i][0]+" is an invalid number value", "exec"); return false; } args.push(Number(remainingArgumentPairs[i][0])); } else if (remainingArgumentPairs[i][1].toLowerCase() == "boolean") { // error handle - the value has a space in front of it (because the syntax requires that you put a space afer the comma when delimiting arguments) var remaningValueString:String = remainingArgumentPairs[i][0].slice(1, remainingArgumentPairs[i][0].length); if (remaningValueString.toLowerCase() == "true" || remaningValueString.toLowerCase() == "false") { args.push(remaningValueString.toLowerCase() == "true" ? true : false); } else { // output an a fatal error, if we didn't do this invalid values would always be false Debugger.showOsError("DebuggerOs.exec() failed-->"+remaningValueString+" is an invalid boolean value in remaining arg#"+(i+1), "exec"); return false; } } else if (remainingArgumentPairs[i][1].toLowerCase() == "string") { args.push(remainingArgumentPairs[i][0].slice(1, remainingArgumentPairs[i][0].length)); } else { Debugger.showOsError("DebuggerOs.exec() failed-->'"+remainingArgumentPairs[i][1]+"' is an invalid datatype.", "exec"); return false; } } // push the final argument args.push(lastArgValue); // dynamically call the method and pass the args, but only call defined functions func = eval(functionString); if (func != undefined) { func.apply(null, args); return true; } else { Debugger.showOsError("DebuggerOs.exec() failed-->the function: "+functionString+" could not be located and probably does not exist!"); return false; } } public function setValue(arg:String):Boolean { // non-local commands like this one need a reference to course if (course == undefined) { course = VLCourse.getInstance(); } // BEGIN: validation var chunks:Array = arg.split('='); if (chunks.length != 2) { Debugger.showOsError("improper usage, the argument: "+arg+" is not valid", "set"); return false; } var obj:Object = eval (chunks[0]); if (obj == undefined) { Debugger.showOsError("the object: "+chunks[0]+" evaluates to undefined. It is either private or doesn't exist.", "setval"); return false; } // validate the value:DataType syntax var valueChunks:Array = chunks[1].split(':'); if (valueChunks.length != 2) { Debugger.showOsError("improper usage, the value and data type: "+chunks[1]+" is not in a valid format", "setval"); return false; } // validate the datatype and set the value on the fly var dataType:String =valueChunks[1].toLowerCase(); switch (dataType) { case "number" : if (isNaN(Number(valueChunks[0]))) { Debugger.showOsError("illegal number value: "+valueChunks[0]+" evaluated to NaN", "setval"); return false; } else { var valu:Number = Number (valueChunks[0]); } break; case "boolean" : if (valueChunks[0].toLowerCase() != "true" && valueChunks[0].toLowerCase() != "false") { Debugger.showOsError("illegal boolean value: "+valueChunks[0]+" must be either true or false.", "setval"); return false; } else { var valu:Boolean = (valueChunks[0].toLowerCase() == "true" ? true : false); } break; case "string" : var valu:String = valueChunks[0]; break; default : Debugger.showOsError("illegal data type: "+dataType+" is not valid, only Number, String and Boolean is supported", "setval"); return false; break; } set (chunks[0], valu); return true; } public function watchProperty(arg:String, isNotCalledByUser:Boolean):Boolean { // non-local commands like this one need a reference to course if (course == undefined) { course = VLCourse.getInstance(); } if (watchlist == undefined) { watchlist = new WatchList ("debugger", Debugger.getInstance().OS); } var objStr:String = arg.slice(0, arg.lastIndexOf('.')); var propStr:String = arg.slice(arg.lastIndexOf('.')+1, arg.length); // validate the object if (eval(objStr) == undefined) { Debugger.showOsError("the object: "+objStr+" evaluated to undefined, it is either private, static or doesn't exist", "watch"); return false; } else if (typeof(eval(objStr)) == "movieclip" || typeof(eval(objStr)) == "string" || typeof(eval(objStr)) == "number" || typeof(eval(objStr)) == "boolean") { Debugger.showOsError("objects of type '"+typeof(eval(objStr))+"' cannot have their properties watched", "watch"); return false; } else if (MiscUtility.isArray(eval(objStr))) { Debugger.showOsError("objects of type 'array' cannot have their properties watched", "watch"); return false; } var obj:Object = eval(objStr); // if we get this far then the object is valid, now validate the value if (eval(arg) == undefined) { Debugger.showOsError("the object: "+objStr+" was found but it's property: "+propStr+" evaluated to undefined, either it is private, static or doesn't exist", "watch"); return false; } else if (typeof(eval(arg)) == "movieclip" || typeof(eval(arg)) == "object") { if (MiscUtility.isArray(eval(arg))) { Debugger.showOsError("properties of type 'array' cannot be watched", "watch"); return false; } // properties that are movieclips or object cannot be watched Debugger.showOsError("properties of type '"+typeof(eval(arg))+"' cannot be watched", "watch"); return false; } // again #@%@ scope it tweaked from here the watchpoint must be set from the debugger class Debugger.watchProperty(objStr, propStr); // track this change in the Watchlist if the watcher is not in there allready if (!watchlist.isWatcher(arg)) { watchlist.addWatcher(arg); } return true; } public function watchList (arg:String) { /*if (watchlist == undefined) { watchlist = new WatchList ("debugger", Debugger.getInstance().OS); }*/ arg = arg.toLowerCase(); switch (arg) { case "save" : // TODO: error handling for failed saves watchlist.saveWatchers(); break; case "erase" : // erase break; case "show" : watchlist.show(); break; case "watchall" : watchlist.watchAll(); default : Debugger.showOsError("the watchlist command failed, the argument: "+arg+" is not valid.", "watchlist"); break; } } public function showWatchResults (prop, oldVal, newVal, path) { Debugger.traceOs("WATCH RESULTS-->the property: "+path+" has changed. The old value was: "+oldVal+" the new value is: "+newVal); } public function unWatchProperty(prop:String):Boolean { Debugger.trace("DebuggerOs-->unWatchProp() received an arg of: "+prop); return true; } private function normalize(str):String { var chaine = unescape(str); var s = ""; for (var i = 0; i31 && cod<122) { s += sc; } } return s; } }