COctreeSceneNode* COctreeSceneNode::InsertObjectIntoChild( ISceneObject* object, Vec3* position, float radius )
{
	// Find out which octant the object is in
	Vec3 nodeSignes;
	int whichNode = ClassifyObject( *position );

	// The node doesn't straddle a boundary
	if( whichNode != -1 )
	{
		// calculate the position of the new octant
		float quarterDim = m_Dimensions * 0.25f;
		Vec3 octantPosition( quarterDim, quarterDim, quarterDim );
		octantPosition *= m_OctantSignes[whichNode];
		octantPosition += m_Position;
		// calculate the new octant dimensions
		float octantDimensions = m_Dimensions * 0.5f;
		
		// If the object fits in the child octant then recurse into the child octant
		if( FitsInNode( *position, radius, octantPosition, octantDimensions ) )
		{
			NewChild( whichNode );

			return m_Children[whichNode]->UpdateSceneObject( object, position, radius );
		}
	}

	return NULL;
}
void processLine(FILE * logf, struct SCRIPT * script, struct TYPING * types, 
				 unsigned long location, struct LINE * line){
	char * tokens = (char *) calloc(TOKENMAXNB*TOKENSIZE,sizeof(char));
	int nbtokens, i, j, index, storobj=-1, valobj=-1; int calldetected;
	
	//Detect system calls
	calldetected = monitorSytemCalls(logf,script,types,location,line);

	//Parse line
	nbtokens = decomposeLine(line->line,tokens,TOKENMAXNB,TOKENSIZE);
	
	for(i=0;i<nbtokens;i++){
		//Monitor string and processing and treat dependency			
		if(!strcasecmp(ACCESS(tokens,i),"Mid")
			||!strcasecmp(ACCESS(tokens,i),"Left")
			||!strcasecmp(ACCESS(tokens,i),"Ucase")
			||!strcasecmp(ACCESS(tokens,i),"Lcase")
			||!strcasecmp(ACCESS(tokens,i),"LTrim")
			||!strcasecmp(ACCESS(tokens,i),"RTrim")
			||!strcasecmp(ACCESS(tokens,i),"Replace")){
			int newstor = 0;
			int obj = isKnownObject(types,ACCESS(tokens,i+1));
			if(obj>-1 && i>=2 && ((char *)ACCESS(tokens,i-1))[0]=='='){
				int storobj = isKnownObject(types,ACCESS(tokens,i-2));
				if(storobj==-1){
					newstor = 1,
					storobj = addNewObject(types,NULL,getObjectNature(types,obj));
					addObjectReference(types,storobj,ACCESS(tokens,i-2));
					setObjectType(types,storobj,getObjectType(types,obj));
				}else{
					setObjectNature(types,storobj,getObjectNature(types,obj));
					setObjectType(types,storobj,getObjectType(types,obj));
				}
				if(newstor){strcpy_s(types->objects[storobj].ObjectName,
							NAME_MAX_LENGTH,types->objects[obj].ObjectName);}
				printLogEntry(logf, types, OP_AFF, storobj, obj);
			}
		}

		//Detect string proceclocal procedure and function calls
		index = isLocalProcedure(script,ACCESS(tokens,i));
		if(index>-1){
			//Avoid recursive calls
			//if((location&0xF0000000)==PROCLEVEL 
			//	&& index==(location&0x0FFFFFFF)){
			if(script->procedureslist[index].beingexecuted){
				printf("[+] Block recursive call to procedure %s\n",
						script->procedureslist[index].name);
			}else{
				script->procedureslist[index].beingexecuted = 1;
				//No return value, so can not be an affectation
				startProcedure(logf,script,types,index,line);
				script->procedureslist[index].beingexecuted = 0;
			}
			free(tokens); return;
		}else{
			index = isLocalFunction(script,ACCESS(tokens,i));
			if(index>-1){
				if(strcmp(ACCESS(tokens,i+1),"=")){//Avoid return values
					//Avoid recursive calls
					if(script->functionslist[index].beingexecuted){
						printf("[+] Block recursive call to function %s\n",
								script->functionslist[index].name);
					}else{
						script->functionslist[index].beingexecuted = 1;
						startFunction(logf,script,types,index,line);
						script->functionslist[index].beingexecuted = 0;
					}
					free(tokens); return;
				}else{
					line->type = AFFECTATION;
					updateReturnStorage(types, 
						script->functionslist[index].name, ACCESS(tokens,i+2));
					free(tokens); return;
				}//if call or return
			}
		}
	} if(calldetected) return;

	//Detect affectation of known object
	for(i=0;i<nbtokens;i++){
		if(((char *)ACCESS(tokens,i))[0]=='='||!strcasecmp(ACCESS(tokens,i),"in")){
			int maxobj = -1; int maxtype; int nullnat = 0;  int newstor = 0;
			int nbconselem; //Number of consecutive elements must
			int isarray = 0;//be < 2 except using & and array to concatenate
			
			//Either creation or retrieving of store object
			storobj = isKnownObject(types,ACCESS(tokens,i-1));
			if(storobj==-1){
				newstor = 1;
				storobj = addNewObject(types,NULL,0);
				addObjectReference(types,storobj,ACCESS(tokens,i-1));
			}//if unknown
			maxtype = getObjectType(types,storobj); 
			nbconselem = 0;

			//Look for significant passing value
			for(j=i+1;j<nbtokens;j++){
				if(!strcasecmp(ACCESS(tokens,j),"Array")){
					isarray = 1; j++;
				}//if
				if(((char *)ACCESS(tokens,j))[0]=='&'){
					nbconselem = 0;	
				}else{ 
					//Checks if access to a static attribute
					char stataccess[TOKENSIZE+5];
					strcpy_s(stataccess,5+TOKENSIZE,ACCESS(tokens,j));
					strcat_s(stataccess,5+TOKENSIZE,".");
					if(strcasestr(line->line,stataccess)){
						nbconselem = 0;
					}else{
						nbconselem++;
					}
				}//if
				if(!isarray && nbconselem>1) break;
				valobj = isKnownObject(types,ACCESS(tokens,j));
				if(valobj>-1){//known objects
					//Update store type when significant
					if(getObjectType(types,valobj)>maxtype){
						maxtype = getObjectType(types,valobj);
						maxobj = valobj;
					}
				}else if(ClassifyObject(ACCESS(tokens,j),&nullnat)>maxtype){//typed object
					maxobj = addNewObject(types,ACCESS(tokens,j),nullnat);
					maxtype = getObjectType(types,maxobj);
				}//if

			}//for
			if(maxobj>-1){
				line->type = AFFECTATION;
				setObjectType(types,storobj,getObjectType(types,maxobj));
				setObjectNature(types,storobj,getObjectNature(types,maxobj));
				if(newstor){strcpy_s(types->objects[storobj].ObjectName,
							NAME_MAX_LENGTH,types->objects[maxobj].ObjectName);}
				printLogEntry(logf, types, OP_AFF, storobj, maxobj);
			}
		}//if '=' found
	}//for
	free(tokens); 
}
void processExpression(FILE * logf, struct SCRIPT * script, struct TYPING * types, 
					   unsigned long location, struct LINE * line,	
					   int tokenindex, int nature, char token[TOKENSIZE], int * next){
	char * tokens = (char *) calloc(TOKENMAXNB*TOKENSIZE,sizeof(char));
	char * stataccess = (char *) calloc(2*TOKENSIZE,sizeof(char));
	char * args = (char *) calloc(TOKENSIZE,sizeof(char));
	int nbtokens, i, obj;
	int type, hightype = 0; int unknown = 1;
	char * wsc = NULL, * attr = NULL;
	
	memset(token,0,TOKENSIZE);
	nbtokens = decomposeLine(line->line,tokens,TOKENMAXNB,TOKENSIZE);
	
	//Missing expression (may be on a next line)
	if(tokenindex>=nbtokens){
		strcpy_s(token,TOKENSIZE,"\"MissingToken\"");
		isMissing = 1;
		return;
	}

	strncpy_s(token,TOKENSIZE,ACCESS(tokens,tokenindex),TOKENSIZE-1);
	for(i=tokenindex; i<nbtokens;){
		
		//Imbricated call (manager.call(args))
		if(script&&possiblyImbricated(ACCESS(tokens,i+1))){
			struct LINE imbricated;
			static int resid = 25;
			char res[TOKENSIZE];
			//Forge a fake line to parse with an intermediate value for storage
			char * imbline = strcasestr((char*)(line->line+2),
												ACCESS(tokens,i));
			if(imbline){
			sprintf_s(res,TOKENSIZE,"INT%08X",resid); resid++;
			sprintf_s(imbricated.line,LINE_LENGTH,"%s = ",res);
			strcat_s(imbricated.line,LINE_LENGTH,imbline);
			//Analyze the intermediate line
			printf("[+] Imbricated call\n");
			processLine(logf,script,types,location,&imbricated);
			strcpy_s(ACCESS(tokens,i),TOKENSIZE,res);}
		}
		
		//Treat special folder
		if(!strcasecmp(ACCESS(tokens,i+1),"GetSpecialFolder")){
			sprintf_s(ACCESS(tokens,i+2),TOKENSIZE,"SpecialDir%d",*ACCESS(tokens,i+2));
			i+=2;
		}

		type = 0;
		obj = isKnownObject(types,ACCESS(tokens,i));
		if(obj>-1){//Object is known and maybe typed
			type = getObjectType(types,obj);
		}else{//Object can be typed
			type = ClassifyObject(ACCESS(tokens,i),&nature);
		}
		
		//Trace the highest typed object
		if(type>hightype){
			hightype = type;
			strncpy_s(token,TOKENSIZE,ACCESS(tokens,i),TOKENSIZE-1);
		}
		
		//If non typed and non string, replace by first known object or encountered string
		if(type==hightype){
			if(unknown && (obj >-1 ||
				(token[0]!='"' && ((char *)ACCESS(tokens,i))[0] == '"'))){
				if(obj>-1) unknown = 0;
				strncpy_s(token,TOKENSIZE,ACCESS(tokens,i),TOKENSIZE-1);
			}else{
				//Avoid unsignificant directory path for false negatives
				if(nature==OBJ_FILE&&!strncasecmp(token,"dir",3))
					strncpy_s(token,TOKENSIZE,ACCESS(tokens,i),TOKENSIZE-1);
			}
		}

		//Checks for static attributes 
		//(Document: body.createTextRange)
		//(Wscript: Fullname, ScriptFullname)
		//(Drive: DriveLetter, VolumeName, Path)
		strcpy_s(stataccess,2*TOKENSIZE,ACCESS(tokens,i)); 
		strcat_s(stataccess,2*TOKENSIZE,".");
		if(strcasestr(line->line,stataccess)){;i++;continue;}

		if(((char *)ACCESS(tokens,i+1))[0]!='&') break; //End of expression
		if(((char *)ACCESS(tokens,i+1))[1]!=0) break; //Case where & is part of the token
		i+=2;
	}//for
	if(next){*next=i+1;}

	free(tokens);
	free(stataccess);
	free(args);
}