#!/bin/bash -p
# rncaudit v1.5e 2005-11-10, Finn Magnusson and David Smith
# Type "rncaudit" on its own for help.

###########################################################################################
# Pathes to files:
###########################################################################################
moshelldir=`dirname "$0"`
if [[ $moshelldir != /* ]] ; then moshelldir=`pwd`/$moshelldir ; fi
funcs="$moshelldir/funcs.awk"
moshell="$moshelldir/moshell"
vobsinstallation=0
unamea=$(uname -a)
gawkext=""
gawklib=""
if [[ $unamea = [Ll][iI][nN][uU][xX]*x86_64* ]] ; then gawklib="lin64"   ; if [[ $vobsinstallation = 1 ]] ; then gawkext=".lin64" ; fi
elif [[ $unamea = [Ll][iI][nN][uU][xX]* ]]      ; then gawklib="linux"   ; if [[ $vobsinstallation = 1 ]] ; then gawkext=".linux" ; fi
elif [[ $unamea = SunOS*sparc* ]]               ; then gawklib="solaris" ; if [[ $vobsinstallation = 1 ]] ; then gawkext=".solaris" ; fi
elif [[ $unamea = SunOS* ]]                     ; then gawklib="sol86"   ; if [[ $vobsinstallation = 1 ]] ; then gawkext=".sol86" ; fi
else gawklib="cygwin" ; gawkext=".exe"
fi
gawkprog="gawk${gawkext}" 
gawk="$moshelldir/$gawkprog"
#special case where moshell has been installed on a linux 32 bit machine but should be run on linux 64 sharing the same file system
if [[ $unamea = [Ll][iI][nN][uU][xX]*x86_64* && $vobsinstallation != 1 && `file "$moshelldir/gawk"` = *32-bit* ]] ; then gawklib="linux" ; fi
filefunc="$moshelldir/commonjars/lib/${gawklib}/filefuncs"
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}$moshelldir/commonjars/lib/${gawklib}
export LANG=C
export LC_ALL=C

logdir="$moshelldir/logfiles/logs_rncaudit"
defLogDir=$moshelldir/commonjars/defLogDir.sh
temp_logdir=$($defLogDir rncaudit)
if [[ -w $temp_logdir && -d $temp_logdir ]] ; then logdir=$temp_logdir ; fi
###########################################################################################

###########################################################################################
#  Specify how to perform the enum comparison
#  enum_comparison=1 means compare by value, ie: the enum attributes in the baseline file should be specified by their value
#  enum_comparison=2 means compare by string, ie: the enum attributes in the baseline file should be specified by their string
###########################################################################################
enum_comparison=1
###########################################################################################

function print_usage()
{
cat <<EOF
***************
Command Syntax:
***************  
  rncaudit <Options> <Argument>

********
Options:
********
  -a <changeAll_file>
Where <changeAll_file> is a Ranos Change_All script.
  -b <baseline_file>
Where <baseline_file> is a parameter list derived from Winnow database.
See example in moshell/examples/audit_files/baseline.txt
This file can be directly exported from the following excel documents:
	n/19059-HSD10102/m,  where: 
	n=3 for RNC      m=3 for P3 
	n=4 for RBS      m=4 for P4 
	n=5 for RXI      m=5 for P5
To compare against a change all script, convert the change_all script to baseline format using the "mocmd" utility.
  -c <cdr_file>
Where <cdr_file> is a file containing cell data (UtranCell, Fach, Rach, Pch).
See example in moshell/examples/audit_files/CDR_celldata.txt
  -r <utranrelation_file>
Where <utranrelation_file> is a file containing a list of all utranrelations.
See example in moshell/examples/audit_files/CDR_utranrelations.txt
  -u <uerc_file>
Where <uerc_file> is a file containing "SET" commands for uerc data (delivered by RAN PU).
See example in moshell/examples/audit_files/UeRc_CXC1326348_R8D02.mo
  -i
Consistency check of internal utranrelations, ie, that they are going both ways and 
that all utranrelations appear in the "reservedBy" list of the UtranCells they are pointing to.
  -e
Consistency check of external utranrelations, ie, that they are going both ways and 
that the ExternalUtranCell attributes match the UtranCell attributes they are referring to.
This option only works when the logdirectory containing all RNC dumps is given as argument.
  -s
Check for duplicated Scrambling Codes in Cell neighbour lists. Checks first tier, second tier and 
third tier collisions.
  -o <outputdir>
Specifies the output directory that will be used (if none is specified then a default will be used).

Note1: Options "-i" and "-e" should not be run before the nodes' data are consistent with the 
CDR file and UtranRelation file. This means that options "-c" and "-r" should be run first,
necessary parameter corrections should be applied to the nodes, new modumps should be taken from
the nodes, and the check can be run using options "-i", "-e". 
The "-s" option should only be run once all other checks have been done and corrections made.
More information in document moshell/examples/audit_files/Audit_procedure_A1.doc

Note2: By copying columns 1,2 and 4 from the result file into a text file and running it through 
the utility "mocmd" (located in moshell directory), it is possible to generate a corrective script 
to be run with moshell/monode or mobatch.

Note3: When running "-b" simultaneously with "-a" and/or "-u", a message is printed if some attributes are checked both in the baseline and one of the other files. The value specified in baseline takes precedence.

*********
Argument:
*********
  - directory containing the modumps 
  OR:
  - modump file
Modumps should be taken with mobatch or monode, using command:
       moshell <ip_address> 'ltc rncfunction;get'  (for dumping one node)
   OR: mobatch <rnc_sitefile> 'ltc rncfunction;get' (for dumping several nodes in parallel)

********
Example:
********
  >> rncaudit -b ./examples/audit_files/baseline.txt \\
  	      -c ./examples/audit_files/CDR_celldata.txt \\
  	      -r ./examples/audit_files/CDR_utranrelations.txt \\
  	      -u ./examples/audit_files/UeRc_CXC1326348_R8D02.mo \\
  	      ./logfiles/logs_mobatch/030630-1830_allRnc/
Make all required corrections on the nodes, take new modumps, then:  	      
  >> rncaudit -ie ./logfiles/logs_mobatch/030705-1810_allRnc/
  		
EOF
}

function check_file_validity()
{
	if ! test -f $1 ; then echo "File not found: $1 . Exiting..." ; exit 1 ; fi
}
function rnc_audit()
{
$gawk -v input_file=$inputfile -v check_changeall=$check_changeall -v changeallfile=$changeallfile -v check_uerc=$check_uerc -v check_baseline=$check_baseline -v check_cdr=$check_cdr -v check_dump=$check_dump -v uercfile=$uercfile -v check_utranrelations=$check_utranrelations -v utranrelationfile=$utranrelationfile -v baselinefile=$baselinefile -v modumpfile=$modumpfile -v cdrfile=$cdrfile -v check_internal=$check_internal -v check_external=$check_external -v check_scr=$check_scr -v resultdir=${resultdir} -v input_file_name=$(basename $inputfile) -v enum_comparison=$enum_comparison -v vobsinstallation="$vobsinstallation" -l "$filefunc" '
BEGIN{
	printf("\n\n*********************************************************************************************\n")
	resultfile=sprintf("%s/%s.res",resultdir,gensub(/\..*$/,"","g",input_file_name))
	printf("Parsing input file %s ...",input_file)
	parse_file(input_file,output1,motype1,inrel,outrel,relationlist,internalcell_list,externalcell_list,psc,ncellLevel1)
	printf("Done.\n\n")
	printf("Results will be saved in %s\n",resultfile)
	print "" > resultfile	
	if (check_baseline == 1) 
	{
		print_output("#############################################################################################\n")
		print_output(sprintf("Parsing baseline file %s ...",baselinefile))
		parse_file(baselinefile,output2,motype2)
		print_output(sprintf("Done.\n"))
		print_output(sprintf("Comparing %s with %s ...\n",input_file,baselinefile))
		compare(output1,output2,motype1,motype2)
		print_output(sprintf("Done.\n"))
	}
	if (check_changeall == 1)
	{
		print_output("#############################################################################################\n")
		print_output(sprintf("Parsing change_all file %s ...",changeallfile))
		parse_changeall(changeallfile,output20,motype20,output2)
		print_output(sprintf("Done.\n"))
		print_output(sprintf("Comparing %s with %s ...\n",input_file,changeallfile))
		compare(output1,output20,motype1,motype20,output2)
		print_output(sprintf("Done.\n"))
	}		
	if (check_uerc == 1)
	{
		print_output("#############################################################################################\n")
		print_output(sprintf("Parsing Uerc MO-set file %s ...",uercfile))
		parse_moscript(uercfile,output3)
		#print_output1(output3)
		print_output(sprintf("Done.\n"))
		print_output(sprintf("Comparing %s with %s ...\n",input_file,uercfile))
		compare(output1,output3,motype1,"",output2)
		print_output(sprintf("Done.\n"))
	}
	if (check_dump == 1)
	{
		print_output("#############################################################################################\n")
		print_output(sprintf("Parsing mo-dump file %s ...",modumpfile))
		parse_file(modumpfile,output5)
		print_output(sprintf("Done.\n"))
		print_output(sprintf("Comparing %s with %s ...\n",input_file,modumpfile))
		compare(output1,output5)
		print_output(sprintf("Done.\n"))
	}			
	if (check_cdr == 1)
	{
		print_output("#############################################################################################\n")
		print_output(sprintf("Parsing CDR file %s ...\n",cdrfile))
		parse_cdr(cdrfile,output4,cell_list)
		print_output(sprintf("Done.\n"))
		print_output(sprintf("Comparing %s with %s ...\n",input_file,cdrfile))
		compare_cdr(output1,output4,cell_list)
		print_output(sprintf("Done.\n"))
	}		
	if (check_utranrelations == 1)
	{
		print_output("#############################################################################################\n")
		print_output(sprintf("Parsing UtranRelations file %s ...",utranrelationfile))
		parse_utranrel(utranrelationfile,cdrlist)
		print_output(sprintf("Done.\n"))
		print_output(sprintf("Comparing %s with %s ...\n",input_file,utranrelationfile))
		compare_utranrel(cdrlist,relationlist,internalcell_list,externalcell_list)
		print_output(sprintf("Done.\n"))
	}
	if (check_internal == 1)
	{
		print_output("#############################################################################################\n")
		print_output(sprintf("Consistency check of internal UtranRelations in %s ...\n",input_file))
		internalrelations(inrel,outrel)
		print_output(sprintf("Done.\n"))
	}
}
function print_output(output)
{
	printf output
	printf output >> resultfile
}
function print_silent(output)
{
	printf "."
	printf output >> resultfile
}
function compare_utranrel(cdrlist,relationlist,internalcell_list,externalcell_list,    missing_in_cdr_int,missing_in_cdr_ext,missing_in_rnc_int,missing_in_rnc_ext,array,missing_cell_def)
{
	for (comb in cdrlist)
	{
		if (cdrlist[comb] != relationlist[comb])
		{
			split(comb,array,SUBSEP)
			if (internalcell_list[array[1]]==1)
			{
				if (internalcell_list[array[2]]==1)				
					missing_in_rnc_int[comb]=1					
				else if (externalcell_list[array[2]]==1)
					missing_in_rnc_ext[comb]=1
				else missing_cell_def[comb]=1
			}
		}
	}
	for (comb in relationlist)
	{
		if (relationlist[comb] != cdrlist[comb])
		{
			split(comb,array,SUBSEP)
			if (internalcell_list[array[1]]==1)
			{
				if (internalcell_list[array[2]]==1)
					missing_in_cdr_int[comb]=1
				else if (externalcell_list[array[2]]==1)
					missing_in_cdr_ext[comb]=1
			}
		}
	}
	print_silent(sprintf("\n==========================================================\n\
List of internal relations missing in RNC\n==========================================================\n"))
	for (comb in missing_in_rnc_int) print_rels(comb)
	print_silent(sprintf("\n==========================================================\n\
List of external relations missing in RNC\n==========================================================\n"))
	for (comb in missing_in_rnc_ext) print_rels(comb)
	print_silent(sprintf("\n==========================================================\n\
List of relations missing in RNC, utrancellref not defined\n==========================================================\n"))
	for (comb in missing_cell_def) print_rels(comb)	
	print_silent(sprintf("\n==========================================================\n\
List of internal relations missing in CDR\n==========================================================\n"))
	for (comb in missing_in_cdr_int) print_rels(comb)
	print_silent(sprintf("\n==========================================================\n\
List of external relations missing in CDR\n==========================================================\n"))
	for (comb in missing_in_cdr_ext) print_rels(comb)
}
	
function print_rels(comb,  array)
{
	split(comb,array,SUBSEP)
	print_silent(sprintf("%s   %s\n",array[1],array[2]))
}

function parse_utranrel(file,output, column)
{
	while (getline < file)
	{
		gsub("\r","")
		if (NF == 2 && $1 ~ /^[0-9]+$/ && tolower($2) ~ /^(utrancell|utrancellref)$/)	
		{
			if (column[tolower($2)]=="") column[tolower($2)]=$1
		}
		else output[$column["utrancell"],$column["utrancellref"]]=1
	}	
}
function internalrelations(inrel,outrel, comb,array,missing,corrupted)
{
	#Check for corrupted relations:
	for (comb in outrel)
	{
		if (outrel[comb]==1)
		{
			if (inrel[comb] != 1) corrupted[comb]=1
		}
	}
	#Check that relations are both ways:
	for (comb in outrel)
	{
		if (outrel[comb]==1)
		{
		split(comb,array,SUBSEP)
		if (outrel[array[2],array[1]] != 1) missing[array[2],array[1]]=1
		}
	}
	for (comb in inrel)
	{
		if (inrel[comb]==1)
		{
		split(comb,array,SUBSEP)
		if (inrel[array[2],array[1]] != 1) missing[array[2],array[1]]=1
		}
	}
	print_silent(sprintf("\n==========================================================\n\
Following relations need to be deleted:\n==========================================================\n"))
	for (comb in corrupted)
	{
		if (corrupted[comb]==1)
		{
		split(comb,array,SUBSEP)
		print_silent(sprintf("%s  %s\n",array[1],array[2]))
		}
	}
	print_silent(sprintf("\n==========================================================\n\
Following relations need to be created:\n==========================================================\n"))
	for (comb in missing)
	{
		if (missing[comb] == 1)
		{
			split(comb,array,SUBSEP)
			print_silent(sprintf("%s  %s\n",array[1],array[2]))
		}
	}
}

function compare(output1,output2,motype1,motype2,output3,  array,mismatch,array1,comb,arrayComb,last,arrayComb1)
{
	#output3 is to give the output from baseline, to use in uetr comparison and change_all comparison
	print_silent("=========================================================================================================\n")
	print_silent(sprintf("%-42s   %-25s   %-15s   %-15s\n","MO","Attribute","Current Value","Required Value"))
	print_silent("=========================================================================================================\n")
	for (comb in output2)
	{
		split(comb,array,SUBSEP) #array[1] is the mo, array[2] the attribute
		if (array[1]~/=/)
		{
			if ((output1[comb] != output2[comb])&&(output1[comb]!="")&&(output2[comb]!=""))
			{
				mismatch[comb]=sprintf("%-15s   %-15s",output1[comb],output2[comb])
				#print comb"        "mismatch[comb]
				split(comb,arrayComb,SUBSEP)
				last=split(arrayComb[1],arrayComb1,",")
				if (output3[comb] != ""  || output3[gensub(/=.*$/,"",1,arrayComb1[last]),arrayComb[2]] !="") 
				{	#printf "x"
					mismatch[comb]=sprintf("%s    #Value set in baseline, ignore",mismatch[comb])
				}
				print_silent(sprintf("%-42s   %-25s   %s\n",array[1],array[2],mismatch[comb]))
			}
		}
		else
		{
			for (comb1 in motype1)
			{
				if (motype1[comb1]==array[1])				
				{
					split(comb1,array1,SUBSEP)
					if (array1[2] == array[2])
					{
						if ((tolower(output1[comb1]) != tolower(output2[comb])) &&(output1[comb1]!="")&&(output2[comb]!=""))
						{
							value1 = value2 = "";
							if (output2[comb] ~ /\([0-9]+\)/)
							{ 
								value1 = gensub(/\(.*$/,"","g",output2[comb]);
								value2 = gensub(/^.*\(|\)$/,"","g",output2[comb]);
								#print "output: " output2[comb] ", value1: " value1 ", value2: " value2;
							} else if (tolower(output2[comb]) ~ /^false$/) {
								value1 = "0";
							} else if (tolower(output2[comb]) ~ /^true$/) {
								value1 = "1";
							}							

							if (tolower(output1[comb1]) != tolower(value1) && tolower(output1[comb1]) != tolower(value2)) 
							{
							 mismatch[comb1]=sprintf("%-10s   %-10s",output1[comb1],output2[comb])
							 #print comb1  "     " mismatch[comb1]
							 split(comb1,arrayComb,SUBSEP)
							 last=split(arrayComb[1],arrayComb1,",")
							 if (output3[comb1] != "" || output3[gensub(/=.*$/,"",1,arrayComb1[last]),arrayComb[2]] !="")
							 {
								mismatch[comb1]=sprintf("%s    #Value set in baseline, ignore",mismatch[comb1])
							 }
							 print_silent(sprintf("%-42s   %-25s    %s\n",array1[1],array1[2],mismatch[comb1]));

							}
							#else { print "said: " output1[comb1] " equal to " value1 " or " value2 }
						}
					}
				}
			}
		}
	}
	print_silent("=========================================================================================================\n")
}
function parse_cdr(file,output,cell_list,  column,site,sector,array,cell,attribute)
{
	#takes the cdr file and output the tables "output" and "cell_list"
	while (getline < file)
	{
		gsub("\r","")
		if (NF ==2 && $1 ~ /^[0-9]+$/)	
		{
			if (column[$1] == "") 
			{
				 column[$1]=tolower($2) #; print $1"   "column[$1]
			}
		}
		else
		{
			site=sector=cell=""
			for (i in column) 
			{
				if (column[i]=="site")   site=i
				if (column[i]=="sector") sector=i
				if (column[i]=="cell")   cell=i
			}
			if (cell=="") cell=tolower(sprintf("%s%s",$site,$sector))
			else cell=tolower($cell)
			cell_list[cell]=cell
			for (i=1;i<=NF;i++)
			{
				split(column[i],array,",")
				attribute=array[2]
				if (array[1] == "utrancell")
				{
					output[sprintf("utrancell=%s",cell),attribute]=$i
					#printf("output[%s,%s]=%s\n",sprintf("utrancell=%s",cell),attribute,$i)
				}
				else if (array[1]  ~ /^(fach|rach|pch)$/) 
				{
					output[sprintf("utrancell=%s,%s=1",cell,array[1]),attribute]=$i
					#printf("output[%s,%s]=%s\n",sprintf("utrancell=%s,%s=1",cell,array[1]),attribute,$i)
				}
			}
		}
	}
}					

function compare_cdr(output1,output2,cell_list,   cell,comb,array,mismatch,cell_comb)
{
	#cdr table is output2
	print_silent("=========================================================================================================\n")
	print_silent(sprintf("%-42s   %-25s   %-15s   %-15s\n","MO","Attribute","Current Value","Required Value"))
	print_silent("=========================================================================================================\n")
	for (comb in output2)
	{
		if ((output1[comb] != output2[comb])&&(output1[comb]!="")&&(output2[comb]!=""))
		{
			mismatch[comb]=sprintf("%-15s    %-15s",output1[comb],output2[comb])
			#print comb "    "mismatch[comb]
		}
	}
	for (comb in mismatch)
	{
		split(comb,array,SUBSEP)
		split(array[1],array,",")
		split(array[1],array,"=")
		cell_comb[comb]=array[2]
	}
	for (cell in cell_list)
	{
		for (comb in mismatch)
		{
			if (cell_comb[comb] == cell)
			{
				split(comb,array,SUBSEP)
				print_silent(sprintf("%-42s   %-25s      %s\n",array[1],array[2],mismatch[comb]))
			}
		}
	}
	print_silent("=========================================================================================================\n")
}
function parse_changeall(file,output,motype,baselineinput,  array)
{
	#RncFunction,1,UtranCell,sf8Adm,8,vD.6.2,-,RNC
	while (getline < file)
	{
		gsub("\r","")
		if (NF > 0)
		{
			split($1,array,",")
			output[tolower(array[3]),tolower(array[4])]=array[5]
			motype[tolower(array[3]),tolower(array[4])]=tolower(array[3])
		}
	}
	close(file)
}
	
function parse_file(file,output,motype,inrel,outrel,relation_list,internalcell_list,externalcell_list,psc,ncellLevel1, \
line,i,maxmember,array,last,var,cell1,cell2,cellname)
{
	while (getline < file)
	{
		gsub("\r","")
		if ($1 ~ /^#/ || NF<2) continue
		last=split($1,array,",")
		motype[tolower($1),tolower($2)]=gensub(/=.*$/,"","g",tolower(array[last]))
		#UTRAN RELATIONS
		if ($1 ~ /^IurLink=.*,ExternalUtranCell=/) externalcell_list[gensub(/^Iur.*UtranCell=/,"","g",$1)]=1		
		else if (($1 ~ /^UtranCell=.*UtranRelation/)&&($2=="utranCellRef"))
		{
			#UtranCell=50735303,UtranRelation=50750102     utranCellRef      IurLink=501502,ExternalUtranCell=50750102
			#UtranCell=50735303,UtranRelation=50740301     utranCellRef      UtranCell=50740301
			cell1=gensub(/^UtranCell=|,UtranRelation=.*$/,"","g",$1)
			internalcell_list[cell1]=1
			cell2=gensub(/^.*UtranCell=/,"","g",$3)
			relation_list[cell1,cell2]=1
			if ($3 ~ /^UtranCell=/)
			{
				#UtranCell=50000701,UtranRelation=50690302                 utranCellRef       UtranCell=50690302
				outrel[cell1,cell2]=1
				#outrel[50000701,50690302]=1
			}
		}			
		else if (($1~/^UtranCell[^,]+$/)&&($2 == "reservedBy")&&($3~/^\[[0-9]+\]$/)&&($4=="="))
		{
			#UtranCell=50690302                                        reservedBy         [19] = 
			# >>> reservedBy = RncFunction=1,UtranCell=50000701,UtranRelation=50690302
			split($3,array,"[") ; split(array[2],array,"]")
			maxmember=array[1]
			cell2=gensub(/^UtranCell=/,"","g",$1)
			for (i=1 ; i<=maxmember;i++)
			{
				getline < file ; gsub("\r","")
				cell1=gensub(/^RncFunction.*UtranCell=|,UtranRelation=.*$/,"","g",$4)
				inrel[cell1,cell2]=1
				#inrel[50000701,50690302]=1
			}

		}		
		#ATTRIBUTES
		else if ((tolower($2) == "userlabel")||($3 ~/\[.*\]/))
			output[tolower($1),tolower($2)]=gensub(/^[ \t]+|[\t ]+$/,"","g",gensub($1,"","1",gensub($2,"","1",$0)))
		else if ($3 ~/Struct\{/)	#}
		{
			# >>> 1.sib1RepPeriod = 32
			var=""
			maxmember=gensub(/Struct\{|\}/,"","g",$3)+0
			for (i=1 ; i<=maxmember; i++)
			{
				getline line < file ; gsub("\r","",line)
				var=sprintf("%s,%s",var,gensub(/[ \t]+|>>> [0-9]+./,"","g",line))
				output[tolower($1),tolower(sprintf("%s.%s",$2,gensub(/^.*\.| =.*$/,"","g",line)))]=gensub(/^.*= /,"","g",line)
				motype[tolower($1),tolower(sprintf("%s.%s",$2,gensub(/^.*\.| =.*$/,"","g",line)))]=gensub(/=.*$/,"","g",tolower(array[last]))
			}
			output[tolower($1),tolower($2)]=gensub(/^,/,"","g",var)   #struct value is case sensitive 
		}
		else if (tolower($3) ~ /^(true|false)$/) output[tolower($1),tolower($2)]=tolower($3)
		else if ($3 ~ /^[0-9]+$/ && $4 ~ /^\(.*\)$/ && NF==4 && enum_comparison==2) output[tolower($1),tolower($2)]=gensub(/\(|\)/,"","g",$4)
		else 
		{
			output[tolower($1),tolower($2)]=$3    
			#printf("output[%s,%s]=%s\n",tolower($1),tolower($2),$3)
		}
	}
}
function parse_moscript(file,output, mo,attribute,attribute_type,maxmember)
{
	#print file
	while (getline < file)
	{
		gsub("\r","")		
		if (/\/\//) sub(/\/.*$/,"",$0)
		if ($1 == "SET")
		{
			#SET
			#(
			#   mo "ManagedElement=1,RncFunction=1,DchFrameSynch=2"
			#  exception none
			#  userLabel String "DchFrameSynch for Packet"
			#)		
			#SET
			#(
			#	mo "ManagedElement=1,RncFunction=1,UeRc=6,UeRcPhyChTfc=7"
			#	exception none
			#	rcTfi Array Integer 5 // 2 DCH used
			#	1
			#	1
			#	0 // not used
			#	0 // not used
			#	0 // not used
			#)
			#SET
			#(
			#   mo "ManagedElement=1,RncFunction=1,UeComb=1"
			#   exception none
			#   ueRrcTypeRef Ref "ManagedElement=1,RncFunction=1,UeRrcType=1"
			#)
			getline < file ; gsub("\r","")
			getline < file ; gsub("\r","")
			mo=tolower(gensub(/\"|ManagedElement=1,|RncFunction=1,|IpSystem=1,|TransportNetwork=1,|SwitchFabric=1,|SwManagement=1,|Equipment=1,/,"","g",$2))
			getline < file ; gsub("\r","")
			getline < file ; gsub("\r","")
			if (/\/\//) sub(/\/.*$/,"",$0)
			if (tolower($1) == "userlabel")
				output[mo,tolower($1)]=gensub(/^[ \t]+|[\t ]+$|\"/,"","g",gensub($1,"","1",gensub($2,"","1",$0)))
			else if (tolower($2) == "array")
			{
				attribute=tolower($1)
				split($3,array,"")
				attribute_type=tolower(array[1])
				maxmember=$4
				attribute_value=sprintf("%s[%s] =",attribute_type,maxmember)
				for (i=1;i<=maxmember;i++)
				{
					getline < file ; gsub("\r","")
					if (/\/\//) sub(/\/.*$/,"",$0)
					attribute_value=sprintf("%s %s",attribute_value,$1)
				}
				output[mo,attribute]=attribute_value
			}
			else if (tolower($2) == "ref")
				output[mo,tolower($1)]=gensub(/\"|ManagedElement=1,|RncFunction=1,|IpSystem=1,|TransportNetwork=1,|SwitchFabric=1,|SwManagement=1,|Equipment=1,/,"","g",$3)
			else
				output[mo,tolower($1)]=$3
		}		
	}
}
function print_output1(output)
{
	for (comb in output)
	{
		split(comb,array,SUBSEP)
		#if ((tolower(array[1]) ~ /^sid/) || (tolower(array[2]) == "rctfi"))
		#{
			printf("%s   %s           %s\n",tolower(array[1]),tolower(array[2]),output[tolower(array[1]),tolower(array[2])])
			#printf("%s   %s           %s\n",tolower(array[1]),tolower(array[2]),motype[tolower(array[1]),tolower(array[2])])
		#}
	}	
}
'
}


function external_check()
{
$gawk -v inputdir=$1 -v resultfile="$resultdir/external_relations.res" -v moshell="$moshell" -v moshelldir="$moshelldir" -f "$funcs" --source '
BEGIN{ 
run_external_check()
}
function run_external_check(  cell1,cell2)
{
	print_output(sprintf("\n\n******************************************************************************\n"))
	print_output(sprintf("Consistency check of external UtranRelations ...\n\n"))
	printf("Results will be saved in %s\n",resultfile)
	print "" > resultfile	
	loadFilefuncs()
	nr_of_files=fileOps("ls "inputdir,fileList)
	if (nr_of_files <= 0)
	{
		print "Directory is empty or cannot be read"
		exit
	}
	for (i=1;i<=nr_of_files;i++)
	{
		inputfile=sprintf("%s/%s",inputdir,fileList[i])
		print "Parsing file "inputfile
		while (getline < inputfile)
		{
			sub("\r","",$0)
			if ($1 == "RncFunction=1" && $2=="rncId") 
			{
				#RncFunction=1                                             rncId              303
				currentRnc=$3
				rncList[$3]=$3
			}
			else if (($1 ~ /^UtranCell=/)&&($3 ~ /^IurLink=/))
			{
				#UtranCell=22260101,UtranRelation=22230102    utranCellRef       IurLink=205203,ExternalUtranCell=22230102
				cell1=gensub(/^UtranCell=|,UtranRelation=.*$/,"","g",$1)
				cell2=gensub(/^.*ExternalUtranCell=/,"","g",$3)
				iurid=gensub(/^IurLink=|,ExternalUtranCell=.*$/,"","g",$3)
				extrelto[cell1,cell2]=1
				extrelfrom[cell2,cell1]=1
				iurlink[cell2]=iurid		
				#print cell2" "iurid
			}
			else if (($1 ~ /^IurLink=/)&&($2=="reservedBy"))
			{
				#IurLink=201203,ExternalUtranCell=20460502                 reservedBy  			
				iurid=gensub(/^IurLink=|,ExternalUtranCell=.*$/,"","g",$1)
				cellid=gensub(/^.*ExternalUtranCell=/,"","g",$1)
				iurlink[cellid]=iurid
			}
			else if (($1~/^IurLink=/)&&($2=="rncId"))
			{
				#IurLink=201205               rncId              205
				iurid=gensub(/^IurLink=/,"","g",$1)
				rncid=$3
				iur_rnc[iurid]=rncid
				rnc_iur[rncid]=iurid
				#print iurid"    "rncid
			}
			else if ($1 ~ /^UtranCell=[^,]+$/)		
			{
				cellid=gensub(/^UtranCell=/,"","g",$1)
				attribute=tolower($2)
				internal_param[cellid,attribute]=$3
				cell_rnc[cellid]=currentRnc						
				#print cellid"   "attribute"    "internal_param[cellid,attribute]
			}
			else if ($1 ~ /^IurLink=.*ExternalUtranCell=[^,]+$/)
			{
				cellid=gensub(/^.*ExternalUtranCell=/,"","g",$1)
				iurid=gensub(/^IurLink=|,ExternalUtranCell=.*$/,"","g",$1)			
				cell_rnc_external[iurid,cellid]=currentRnc						
				attribute=tolower($2)
				if (attribute !~ /userlabel|reservedby|maxtxpowerul|qqualmin|qrxlevmin|lac|rac|externalutrancellid/) 
					external_param[iurid,cellid,attribute]=$3
			}
		}
		close(inputfile)
	}
	#for (a in iurlink)
	#{
	#	#print a, iurlink[a], iur_rnc[iurlink[a]]
	#	cell_rnc[a]=iur_rnc[iurlink[a]]
	#}
	for (a in extrelto)
	{
			if (extrelfrom[a]==1) 
			{
				delete extrelfrom[a]
				delete extrelto[a]
			}
	}
	#total=0
	for (a in extrelto)
	{
		if (extrelto[a]==1)
		{
			split(a,array,SUBSEP)
			missingrel[array[2],array[1]]=cell_rnc[array[2]]
			#print array[2]"  "array[1]"  "cell_rnc[array[2]]
			#total++
		}
	}
	for (a in rnc_iur)
	{
		print_silent(sprintf("ExternalUtranRelations missing in RNC %s\n",a))
		print_silent(sprintf("%-20s  %s\n","from cell","to iurlink-cell"))
		#subtotal=0
		for (b in missingrel)
		{
			if (missingrel[b]==a)
			{
				split(b,array,SUBSEP)
				print_silent(sprintf("%-20s  %s-%s\n",array[1],iurlink[array[2]],array[2]))
				#subtotal++
			}
		}
		#print ">>> Total: "subtotal".\n"
	}
	#print ">>> Total: "total".\n"
	for (comb in external_param)
	{
		split(comb,array,SUBSEP)
		if (external_param[comb] != internal_param[array[2],array[3]])
		{
			#print comb"      "internal_param[comb]"    "external_param[comb]
			split(comb,array,SUBSEP)
			param_mismatch[comb]=cell_rnc_external[array[1],array[2]]
		}
	}	
	for (a in rnc_iur)
	{
		print_output(sprintf("\nExternal Cell data Mismatch in RNC %s\n",a))
		print_silent(sprintf("%-30s      %-30s      %-10s      %-15s  %-s\n","ExternalCell","Attribute","Value","InternalCellRnc","InternalCellValue"))
		#subtotal=0
		for (comb in param_mismatch)
		{
			if (param_mismatch[comb]==a)
			{
				split(comb,array,SUBSEP)
				print_silent(sprintf("%-30s      %-30s      %-10s      %-15s  %-s\n",array[1]"-"array[2],array[3],external_param[comb],cell_rnc[array[2]],internal_param[array[2],array[3]]))
			}
		}
	}
	print_output("\n")
	#for (a in rnc_iur)
	#{
	#	print "\nMoshell scripts to be loaded in RNC "a
	#	printf("lt rncfunction|utrancell|iurlink\ny\n")
	#	for (b in missingrel)
	#	{
	#		if (missingrel[b]==a)
	#		{
	#			split(b,array,SUBSEP)
	#			printf("cr rncfunction=1,utrancell=%s,utranrelation=%s\n",array[1],array[2])
	#			printf("rncfunction=1,iurlink=%s,externalutrancell=%s\n",iurlink[array[2]],array[2])
	#		}
	#	}
	#}
	

}
function print_output(output)
{
	printf output
	printf output >> resultfile
}
function print_silent(output)
{
	printf "."
	printf output >> resultfile
}

'
}


function duplicateScr()
{
$gawk -v inputdir=$inputdir -v resultdir=$resultdir '
BEGIN { 
	while (sprintf("ls -l %s",inputdir) |& getline) 
	{
		gsub("\r","")
		if ($1 ~ /^-rw/)
		{
			i++
			inputfile[i]=sprintf("%s/%s",inputdir,$NF)
			inputfilename[i]=$NF
			sitename[i]=gensub(/\..*$/,"","g",$NF)
			resultfile[i]=sprintf("%s/%s.res",resultdir,sitename[i])
			printf("") > resultfile[i] 
			close(resultfile[i])
			#printf("inputfile[%s]=%s  inputfilename[%s]=%s\n",i,inputfile[i],i,inputfilename[i])
		}
	}
	close(sprintf("ls -l %s",input_dir))
	nr_of_files=i 
	print "#############################################################################################"
	printf("Check for duplicated Scrambling Codes in Cell neighbour lists ...\n")
	printf("Results will be saved in %s\n",resultdir)
	for (i=1;i<=nr_of_files;i++)
	{
		printf("Parsing input file %s ...",inputfile[i])
		parse_file(inputfile[i],resultfile[i])
		printf("Done.\n")
	}
	duplicateScr(ncellLevel1,psc)
}

function parse_file(inputfile,resultfile, i,last)
{
	while (getline < inputfile)
	{
		gsub("\r","")
		#DUPLICATED SCRAMBLING CODES IN NEIGHBOUR LIST
		if ($1 ~ /^UtranCell=/ && $2=="primaryScramblingCode")
		{
			psc[gensub(/^UtranCell=/,"",1,$1)]=$3
			#print "psc["gensub(/^UtranCell=/,"",1,$1)"]="psc[gensub(/^UtranCell=/,"",1,$1)]
		}
		if ($1 ~ /^IurLink.*ExternalUtranCell=/ && $2 =="primaryScramblingCode")
		{
			altPsc[gensub(/^.*UtranCell=/,"",1,$1)]=$3
		}
		if (($1 ~ /^UtranCell=.*UtranRelation/)&&($2=="utranCellRef"))
		{
			split($1,array,",")
			cellname=gensub(/^.*UtranCell=/,"",1,array[1])
			ncellLevel1[cellname]=sprintf("%s;%s",ncellLevel1[cellname],gensub(/^.*UtranCell=/,"",1,$3))
			resFile[cellname]=resultfile
			#print "ncellLevel1["cellname"]="ncellLevel1[cellname]
		}
	}
	close(inputfile)
	for (cell in resFile) resFileList[resFile[cell]]=resFile[cell]
	for (cell in ncellLevel1)
	{
		last=split(ncellLevel1[cell],array,";")
		for (i=2;i<=last;i++)
		{
			if (psc[array[i]]=="") psc[array[i]]=altPsc[array[i]]
		}
	}
}
function duplicateScr(ncellLevel1,psc,    \
cell,i,last,array,npscLevel1,arrayPsc,arrayCell,occurrence,firstOccurrence,comb,combarray,cellarray,multiplePsc)
{
	#ncellLevel1[30840102]=;30940302;30450601;...
	#npscLevel1[30840102]=;45;57;...
	#psc[308401]=34
	#ncellLevel2[cell]=;ncell1-cell1;ncell1-cell2;ncell1-cell3;ncell2-cell1;....
	#npscLevel2[cell]=;psc1;psc2;psc3;...
	for (cell in ncellLevel1)
	{
		last=split(ncellLevel1[cell],array,";")
		for (i=2;i<=last;i++)
		{
			npscLevel1[cell]=sprintf("%s;%s",npscLevel1[cell],psc[array[i]])
			last2=split(ncellLevel1[array[i]],array2,";")
			for (j=2;j<=last2;j++)
			{
				ncellLevel2[cell]=sprintf("%s;%s->%s",ncellLevel2[cell],array[i],array2[j])
				npscLevel2[cell]=sprintf("%s;%s",npscLevel2[cell],psc[array2[j]])
			}
		}
	}
	for (cell in npscLevel1)
	{
		last=split(npscLevel1[cell],arrayPsc,";")
		split(ncellLevel1[cell],arrayCell,";")
		for (i=2;i<=last;i++)
		{
			occurrence[arrayPsc[i]]++
			if (occurrence[arrayPsc[i]]==1) firstOccurrence[arrayPsc[i]]=arrayCell[i]
			else if (occurrence[arrayPsc[i]]>1)
			{
				if (occurrence[arrayPsc[i]]==2) multiplePsc[cell,arrayPsc[i]]=firstOccurrence[arrayPsc[i]]
				multiplePsc[cell,arrayPsc[i]]=sprintf("%s;%s",multiplePsc[cell,arrayPsc[i]],arrayCell[i])
			}
		}
		delete occurrence
	}
	for (resultFile in resFileList)
	{
		printf("\n----------------------------------------------------------\n\
First Tier Check (pScr duplication within primary neighbour list)\n\
----------------------------------------------------------\n\
%-10s  %-4s  %s\n","Cell","pScr","1st level Neighbours") >> resultFile
	}
	for (comb in multiplePsc)
	{
		split(comb,combarray,SUBSEP)
		last=split(multiplePsc[comb],cellarray,";")
		printf("%-10s  %-4s",combarray[1],combarray[2]) >> resFile[combarray[1]]
		for (i=1;i<=last;i++)
		{
			printf("  %s ",cellarray[i]) >> resFile[combarray[1]]
		}
		print "" >> resFile[combarray[1]]
	}
	delete multiplePsc
	for (cell in npscLevel1)
	{
		last1=split(npscLevel1[cell],arrayPsc1,";")
		last2=split(npscLevel2[cell],arrayPsc2,";")
		split(ncellLevel1[cell],arrayCell1,";")
		split(ncellLevel2[cell],arrayCell2,";")
		for (i=2;i<=last1;i++)
		{
			for (j=2;j<=last2;j++)
			{
				if (arrayPsc2[j]==arrayPsc1[i])
				{
					if (arrayCell1[i] != gensub(/^.*->/,"",1,arrayCell2[j])) multiplePsc[cell,arrayCell1[i]]=sprintf("%s;%s",multiplePsc[cell,arrayCell1[i]],arrayCell2[j])
				}
			}
		}
	}				
	for (resultFile in resFileList)
	{
		printf("\n----------------------------------------------------------\n\
Second Tier Check (pScr duplication between primary neighbour list and secondary/composite neighbour list)\n\
----------------------------------------------------------\n\
%-10s  %-4s %-16s %-17s %s\n","Cell;","pScr;","1st level Neighb;","2nd level Neighb;","Path to 2nd level Neighb") >> resultFile
	}
	for (comb in multiplePsc)
	{
		delete differentCells
		split(comb,combarray,SUBSEP)
		last=split(multiplePsc[comb],arraycell,";")
		printf("%-10s  %-4s  %-16s  ",combarray[1]";",psc[combarray[2]]";",combarray[2]";") >> resFile[combarray[1]]
		for (i=2;i<=last;i++) 
		{
			differentCells[gensub(/^.*->/,"",1,arraycell[i])]=1
		}
		for (cell in differentCells) printf("%s  ",cell) >> resFile[combarray[1]]
		printf(";") >> resFile[combarray[1]]
		for (i=2;i<=last;i++) printf("%s  ",arraycell[i]) >> resFile[combarray[1]]
		print "" >> resFile[combarray[1]]
	}
	delete multiplePsc
	for (cell in npscLevel2)
	{
		last2=split(npscLevel2[cell],arrayPsc,";")
		split(ncellLevel2[cell],arrayCell,";")
		for (i=2;i<=last2;i++)
		{
			occurrence[arrayPsc[i]]++
			if (occurrence[arrayPsc[i]]==1) firstOccurrence[arrayPsc[i]]=arrayCell[i]
			else if (occurrence[arrayPsc[i]]>1)
			{
				if (occurrence[arrayPsc[i]]==2) multiplePsc[cell,arrayPsc[i]]=firstOccurrence[arrayPsc[i]]
				multiplePsc[cell,arrayPsc[i]]=sprintf("%s;%s",multiplePsc[cell,arrayPsc[i]],arrayCell[i])
			}
		}
		delete occurrence
	}
	for (resultFile in resFileList)
	{
		printf("\n----------------------------------------------------------\n\
Third Tier Check (pScr duplication within secondary/composite neighbour list)\n\
----------------------------------------------------------\n\
%-10s  %-4s  %s  %s\n","Cell;","pScr;","2nd level Neighbours;","Path to 2nd level Neighbours") >> resultFile
	}
	#multiplePsc[cell,psc]=50720203->50660103;50720103->50660103;50720102->50660103;50700202->50660103;50670201->50660103 
	for (comb in multiplePsc)
	{
		split(comb,combarray,SUBSEP)
		delete differentCells
		nr=0
		last=split(multiplePsc[comb],cellarray,";")
		for (i=1;i<=last;i++)
		{
			differentCells[gensub(/^.*->/,"",1,cellarray[i])]=1
		}
		for (cell in differentCells) nr++
		if (nr > 1)
		{
			printf("%-10s  %-4s  ",combarray[1]";",combarray[2]";") >> resFile[combarray[1]]
			for (cell in differentCells)
			{
				printf(" %s",cell) >> resFile[combarray[1]]
			}
			printf(" ; ") >> resFile[combarray[1]]
			for (i=1;i<=last;i++)
			{
				printf("%s ",cellarray[i]) >> resFile[combarray[1]]
			}
			print "" >> resFile[combarray[1]]
		}
	}
	delete multiplePsc
}
'
}

echo -e "\033[1;31m\n!!!! WARNING: Options -a, -b, -u are obsolete, use the moshell command \"diff\" instead !!!! \n\033[0m"

check_changeall=0
check_cdr=0
check_uerc=0
check_baseline=0
check_dump=0
check_utranrelations=0
check_internal=0
check_external=0
check_scr=0
run_rncaudit=0
while getopts "a:c:u:b:d:r:o:ies" options
do
case $options in
a) changeallfile=$OPTARG
   check_changeall=1
   check_file_validity $changeallfile
   run_rncaudit=1
   ;;
c) cdrfile=$OPTARG
   check_cdr=1
   check_file_validity $cdrfile
   run_rncaudit=1
  ;;   
u) uercfile=$OPTARG
   check_uerc=1
   check_file_validity $uercfile
   run_rncaudit=1
   ;;
b) baselinefile=$OPTARG
   check_baseline=1
   check_file_validity $baselinefile
   run_rncaudit=1
  ;;    
d) modumpfile=$OPTARG
   check_dump=1
   check_file_validity $modumpfile
   run_rncaudit=1
   ;;  
r) utranrelationfile=$OPTARG   
   check_utranrelations=1
   check_file_validity $utranrelationfile
   run_rncaudit=1
   ;;
o) resultdir=$OPTARG
   ;;
i) check_internal=1
   run_rncaudit=1
    ;;
e) check_external=1
    ;;    
s) check_scr=1
   ;;
*) print_usage ; exit 1
  ;;
esac
done 
shift $(($OPTIND - 1))
if test $OPTIND -eq 1 ; then print_usage ; exit 1; fi

case $# in
1)  if test -f "$1" ; then inputfile="$1" ; input="file" ; inputbase=$(basename $inputfile)
    elif test -d "$1" ; then inputdir="$1" ; input="dir" ; inputbase=$(basename $inputdir)
    else echo "File/Directory $1 not found. Exiting...." ; exit 1
    fi
    ;;    
*) print_usage ; exit 1
  ;;   
esac

date_time=$(date +%y%m%d-%H%M)
if [[ $inputbase = "." ]] ; then inputbase="" ; fi
if [[ -z "$resultdir" ]]; then
	resultdir=${logdir}/${date_time}_${inputbase}
fi

if [[ ! -d $resultdir ]]; then
	if ! mkdir -p $resultdir ; then "Failed to create result directory: $resultdir . Exiting ..." ; exit 1 ; fi 
fi

if [[ $input == "file" && $run_rncaudit -eq 1 ]] ; then rnc_audit ; fi
if [[ $input == "file" ]] ; then
	if test $check_external -eq 1
	then
		echo -e "\n!!! In order to check external relations consistency, the directory containing modumps for all neighbouring RNCs must be given as argument.!!!\n"
	fi
	if test $check_scr -eq 1
	then
		echo -e "\n!!! In order to check scrambling code duplication in cells neighbour lists, the directory containing modumps for all neighbouring RNCs must be given as argument.!!!\n"
	fi
elif test $input == "dir"
then
	if [[ $run_rncaudit -eq 1 ]] ; then
		for file in $inputdir/*
		do 
			inputfile=$file
			rnc_audit
		done
	fi
	if test $check_external -eq 1 
	then
		external_check $inputdir
	fi
	if test $check_scr -eq 1
	then
		duplicateScr
	fi			
fi
		
