sdkcreationmw/sdkbuild/SDK_WINSCW/ifsheets.pm
changeset 0 b26acd06ea60
equal deleted inserted replaced
-1:000000000000 0:b26acd06ea60
       
     1 #
       
     2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 #
       
    16 
       
    17 package ifsheets;
       
    18 ############################################
       
    19 # 13.6.2005: 
       
    20 #  - Added support for the Removed column in the black list.
       
    21 #  - Added support for "For Adaptation" And "Extended SDK" columns
       
    22 #    in the readInfo*2 functions (just to read the data into the hash).
       
    23 #  - currently there is NO support to get extended SDK /for adaptation API lists
       
    24 #    based on some release.
       
    25 ############################################
       
    26 
       
    27 
       
    28 ##########################################
       
    29 # Libraries used
       
    30 ##########################################
       
    31 use strict;
       
    32 use Win32::OLE qw(in with);
       
    33 use Win32::OLE::Const 'Microsoft Excel';
       
    34 use Exporter ();     # Needed to make constants available to caller.
       
    35 use excel_support;    # opening/closing workbook, etc.. functions.
       
    36 
       
    37 ##########################################
       
    38 # Defining all the "global" variables, that we are using.
       
    39 ##########################################
       
    40 use vars qw(
       
    41             @ISA
       
    42             @EXPORT
       
    43             );
       
    44 
       
    45 @ISA = qw(Exporter); # Inherit from Exporter module (import method needed).
       
    46 
       
    47 # Define all the functions defined by this module
       
    48 use subs qw(
       
    49 	    isSupported
       
    50 	    addToHash
       
    51 	    isRowWanted
       
    52 	    setRowValue
       
    53 	    getError
       
    54 	    checkRel
       
    55 	    checkApiRelRoadMap
       
    56 	    checkFileRelRoadMap
       
    57 	    readInfo
       
    58 	    checkConflicts
       
    59 	    readInfo2
       
    60 	    readCRepInfo2
       
    61 	    readBlackList
       
    62 	    );
       
    63 
       
    64 ##########################################
       
    65 # Define the exports from this module that can be used
       
    66 # Outside
       
    67 ##########################################
       
    68 @EXPORT = qw(
       
    69              &getExcelApp
       
    70 	     &quitExcelApp
       
    71 	     &isSupported
       
    72 	     &openWorkbook
       
    73 	     &getWorkSheet
       
    74 	     &readInfo
       
    75 	     &checkConflicts
       
    76 	     &readInfo2
       
    77 	     &readCRepInfo2
       
    78 	     &readBlackList
       
    79              );
       
    80 
       
    81 
       
    82 ##########################################
       
    83 # Global variables inside this module (constants
       
    84 ##########################################
       
    85 # For 2.0 template version there are 32 columns
       
    86 my $globalMaxColCount = 32;
       
    87 
       
    88 # How many empty lines we are allowed to encounter before we 
       
    89 # stop handling specific sheet. 
       
    90 my $globalMaxEmptyRowCount = 10;
       
    91 
       
    92 my $currFileName = "";
       
    93 
       
    94 ##########################################
       
    95 # Error constants
       
    96 ##########################################
       
    97 my $TEMPLATE_SYNTAX_ERROR = 0;
       
    98 my $API_DESC_MISSING_ERROR = 10;
       
    99 my $API_REL_MISSING_ERROR = 11;
       
   100 my $API_REL_SYNTAX_ERROR = 12;
       
   101 my $API_REL_LOGICAL_ERROR = 13;
       
   102 my $API_HEADERS_IN_ROW_ERROR = 14;
       
   103 my $API_ADAPTATION_ERROR = 15;
       
   104 my $DLL_SYNTAX_ERROR = 20;
       
   105 my $LIB_SYNTAX_ERROR = 30;
       
   106 my $FILE_MORE_THAN_ONE_FILE_ERROR = 40;
       
   107 my $FILE_COLUMN_SYNTAX_ERROR = 41;
       
   108 my $FILE_REL_SYNTAX_ERROR = 42;
       
   109 my $FILE_REL_LOGICAL_ERROR = 43;
       
   110 
       
   111 
       
   112 
       
   113 ###########################################################################
       
   114 # Functions checks if the template version is supported or not.
       
   115 #
       
   116 # We only support template version 1.5,1.5.1 and 1.6
       
   117 # From 1.5 onwards the template version is located in the "Instructions"-sheet
       
   118 #
       
   119 # Params: refToWorkbook,refToTemplateVersion
       
   120 #
       
   121 # Return: 0 not supported
       
   122 #         1 is supported
       
   123 #
       
   124 #         Also the found template version is stored to the refToTemplateVersion
       
   125 ###########################################################################
       
   126 sub isSupported
       
   127 {
       
   128     my $refToWb = shift;
       
   129     my $refToTemplateVersion = shift;
       
   130 
       
   131     # Get the instructions sheet, since it contains the template version.
       
   132     my $refToWorksheet = getWorkSheet $refToWb,"Instructions";
       
   133 
       
   134     # The instructions sheet => then try the main page. In 1.8 the instructions
       
   135     # page was removed.
       
   136     if(! defined($refToWorksheet))
       
   137     {
       
   138 	$refToWorksheet = getWorkSheet $refToWb,"Main";
       
   139     }
       
   140 
       
   141     # No main or instructions sheet => not supported.
       
   142     if(! defined($refToWorksheet))
       
   143     {
       
   144 	return 0;
       
   145     }
       
   146 
       
   147     # the template version in in cell C2. (both tabs the place is same)
       
   148     my $templVersion  = $$refToWorksheet->Cells( 2, 3  )->{ 'Value' };
       
   149     
       
   150     if(defined($refToTemplateVersion))
       
   151     {
       
   152 	$$refToTemplateVersion = $templVersion;
       
   153     }
       
   154 
       
   155     # Support version 1.5 and 1.5.1
       
   156     if( defined($templVersion) && $templVersion =~ /^\s*1\.5(\.1)*$/)
       
   157     {
       
   158 	return 1;
       
   159     }
       
   160     # Support version 1.6
       
   161     if( defined($templVersion) && $templVersion =~ /^\s*1\.6$/)
       
   162     {
       
   163 	return 1;
       
   164     }
       
   165     # Support version 1.7 and 1.7.*
       
   166     if( defined($templVersion) && $templVersion =~ /^\s*1\.7(\.[0-9]+)*$/)
       
   167     {
       
   168 	return 1;
       
   169     }
       
   170     # Support version 1.8 and 1.8.*
       
   171     if( defined($templVersion) && $templVersion =~ /^\s*1\.8(\.[0-9]+)*$/)
       
   172     {
       
   173 	return 1;
       
   174     }
       
   175     # Support version 1.9 and 1.9.*
       
   176     if( defined($templVersion) && $templVersion =~ /^\s*1\.9(\.[0-9]+)*$/)
       
   177     {
       
   178 	return 1;
       
   179     }
       
   180     # Support version 2.0 and 2.0.*
       
   181     if( defined($templVersion) && $templVersion =~ /^\s*2\.0(\.[0-9]+)*$/)
       
   182     {
       
   183 	return 1;
       
   184     }
       
   185 
       
   186     return 0;
       
   187 }
       
   188 
       
   189 ###########################################################################
       
   190 # Function defines what is the next api ordinal to be used in the 
       
   191 # hash return by readInfo2 and readCRepInfo2 methods.
       
   192 # there.
       
   193 #
       
   194 # Params: refToHash
       
   195 #
       
   196 # Return: next ordinal
       
   197 ##########################################################################
       
   198 sub sortNumerically
       
   199 {
       
   200     $a <=> $b;
       
   201 }
       
   202 sub getNextOrdinal
       
   203 {
       
   204     my $refToHash = shift;
       
   205 
       
   206 
       
   207     my @ordinalsInOrder =  sort sortNumerically ( keys(%$refToHash));
       
   208     my $highestValue = pop @ordinalsInOrder;
       
   209     $highestValue++;
       
   210 
       
   211     return $highestValue;
       
   212 }
       
   213 
       
   214 ###########################################################################
       
   215 # Function adds the information in the str into the has, if the information is not
       
   216 # there.
       
   217 # It also separates command separated items before adding them
       
   218 #
       
   219 # Params: refToHash, text added.
       
   220 #
       
   221 # Return: -
       
   222 ###########################################################################
       
   223 sub addToHash
       
   224 {
       
   225     my $refToHash = shift;
       
   226     my $str = shift;
       
   227     
       
   228     # No need to do anything, if there is nothing to do.
       
   229     if(! defined($str) || $str =~ /^\s*$/)
       
   230     {
       
   231 	return;
       
   232     } 
       
   233 
       
   234     # The items can be separated by "," and there could be additional
       
   235     # space before of after the separator.
       
   236     my @items = split /\s*[,\n ]+\s*/,$str;
       
   237 
       
   238     my $item;
       
   239     
       
   240     # Add each item to the hash. This is only done, if the item does not
       
   241     # exist there before.
       
   242     foreach $item (@items)
       
   243     {
       
   244 	# all spaces and newlines taken away before addition
       
   245 	$item =~ s/\s*//g;
       
   246 	chomp($item);
       
   247 
       
   248 	
       
   249 	# Add if not added earlier (avoiding duplicate entries)
       
   250 	if( !defined( $$refToHash{$item}) && $item !~ /^\s*N\/A\s*$/i && $item !~ /^\s*\-\s*$/)
       
   251 	{
       
   252 	    # It does not matter what is the value, since we are only interested in the
       
   253 	    # key.
       
   254 	    $$refToHash{$item} = 1; 
       
   255 	}
       
   256     }
       
   257 }
       
   258 ###########################################################################
       
   259 # Function expects to find the fromStr and obsoletedStr in format "Sx0 <rel>, Sx0 <rel>", where x is 6 0r 9.
       
   260 # It tries to determinate, if the range matches to the given release for the given platform
       
   261 # Possible combinations "", "S60 <rel>","S90 <rel>","S60 <rel>, S90 <Rel>"
       
   262 #
       
   263 # Params: plat, rel, isAPIrow,fromStr, obsoletedStr
       
   264 #
       
   265 # Return:
       
   266 #   1 is part of wanted platform
       
   267 #   2 has been removed in this/prev releases
       
   268 #   3 is coming in future releases
       
   269 #   4 no release for the API in given str
       
   270 # Note: 0 is used outside of this function.
       
   271 ###########################################################################
       
   272 sub isRowWanted
       
   273 {
       
   274     my $plat = shift;
       
   275     my $rel = shift;
       
   276     my $isApiRow = shift;
       
   277     my $fromStr = shift;
       
   278     my $obsoletedStr = shift;
       
   279     
       
   280     #######################################################
       
   281     # First check the obsoleted field. If that matches, it really does not matter
       
   282     # what is the from string.
       
   283     #######################################################
       
   284     if(defined($obsoletedStr) && $obsoletedStr =~ /$plat/i)
       
   285     {
       
   286 	# the value was defined and contains the platform wanted.
       
   287 	# Now extract the release for the wanted platform.
       
   288 	if($obsoletedStr =~ /$plat\s+([0-9.]+)/i)
       
   289 	{
       
   290 	    my $obsoletedRelInSheet = $1;
       
   291 	
       
   292 	    # check, if the line has been obsoleted, if yes then return false.
       
   293 	    if($rel >= $obsoletedRelInSheet)
       
   294 	    {
       
   295 		return 2;
       
   296 	    }
       
   297 	}
       
   298     }
       
   299 
       
   300     #######################################################
       
   301     # If the row was not obsoleted, then check the from-value.
       
   302     #######################################################
       
   303 
       
   304     # If there is no value in the field the item is handled differently depending
       
   305     # if the row is API row or header row.
       
   306     if( ! defined($fromStr) || $fromStr =~ /^\s*$/ ||  $fromStr !~ /$plat/i)
       
   307     {
       
   308 	return 4;
       
   309     }
       
   310     
       
   311     # The platform was specified in the field. Now find out the number
       
   312     if($fromStr =~ /$plat\s+([0-9.]+)/i)
       
   313     {
       
   314 	my $platRelInSheet = $1;
       
   315 	if( $rel >= $platRelInSheet)
       
   316 	{
       
   317 	    # belongs to the release
       
   318 	    return 1;
       
   319 	}
       
   320 	else
       
   321 	{
       
   322 	    # does not belong to the release
       
   323 	    return 3;
       
   324 	}
       
   325     }
       
   326 
       
   327     # We should only come here, if the information was somehow wrongly specified.
       
   328     # (for instance numbers in the release was not a number, but something else)
       
   329     return 4;
       
   330 }
       
   331 
       
   332 
       
   333 ###########################################################################
       
   334 # function sets the given rel value, if the value was defined
       
   335 #
       
   336 # Params: referenceToVariable, value
       
   337 #
       
   338 ###########################################################################
       
   339 sub setRelValue
       
   340 {
       
   341     my $refToVar = shift;
       
   342     my $value = shift;
       
   343 
       
   344     if(defined($value) && $value !~ /^\s*$/)
       
   345     {
       
   346 	$$refToVar = $value;
       
   347     }
       
   348 }
       
   349 
       
   350 ###########################################################################
       
   351 # Function generates an error item
       
   352 #
       
   353 # Params: errNbr, ... <other information>
       
   354 #
       
   355 # Return: reference to an error item list
       
   356 ###########################################################################
       
   357 sub getError
       
   358 {
       
   359     my $errNbr = shift;
       
   360     my $refToDetailsList = \@_;
       
   361     
       
   362     my @errItem;
       
   363     push(@errItem,$errNbr);
       
   364     push(@errItem,$currFileName);
       
   365     push(@errItem,@$refToDetailsList);
       
   366    
       
   367     return \@errItem;
       
   368 }
       
   369 
       
   370 
       
   371 ###########################################################################
       
   372 # Checks the syntax of the given release field
       
   373 #
       
   374 # Params: checked rel value
       
   375 #
       
   376 # Return:  0 OK
       
   377 #         >0 NOK
       
   378 ###########################################################################
       
   379 sub checkRel
       
   380 {
       
   381     my $checkedRel = shift;
       
   382 
       
   383     # No value defined => return OK
       
   384     if($checkedRel == -1)
       
   385     {
       
   386 	return 0;
       
   387     }
       
   388 
       
   389     # Only S60 or S90 release specified
       
   390     if($checkedRel =~ /^\s*S[69]0 [0-9]+\.[0-9]+\s*$/i)
       
   391     {
       
   392 	return 0;
       
   393     }
       
   394     # Both S60 or S90 release specified
       
   395     if($checkedRel =~ /^\s*S[69]0 [0-9]+\.[0-9]+\s*\,\s*S[69]0 [0-9]+\.[0-9]+\s*$/i)
       
   396     {
       
   397 	return 0;
       
   398     }
       
   399     
       
   400     # Otherwise error
       
   401     return 1;
       
   402 }
       
   403 
       
   404 
       
   405 ###########################################################################
       
   406 # Function checks that the information in the files for given release are OK.
       
   407 #
       
   408 # Params: refToErrList, checkedPlatform, apiName, sdkRel,oemRel,internalRel,privateRel
       
   409 #
       
   410 # Return:  0 no errors found
       
   411 #          > 0 amount of  errors found
       
   412 ###########################################################################
       
   413 sub checkApiRelRoadMap
       
   414 {
       
   415     my $refToErrorList = shift;
       
   416     my $checkedPlatform = shift;
       
   417     my $apiName = shift;
       
   418     my $apiSdkRel = shift;
       
   419     my $apiOemRel = shift;
       
   420     my $apiInternalRel = shift;
       
   421     my $apiPrivateRel = shift;
       
   422     my $apiDeprecatedRel = shift;
       
   423     my $apiObsoletedRel = shift;
       
   424     
       
   425     my $sdk = -1;
       
   426     my $oem = -1;
       
   427     my $int = -1;
       
   428     my $priv = -1;
       
   429     my $dep = -1;
       
   430     my $obs = -1;
       
   431 
       
   432     my $errorsBeforeCheck = scalar(@$refToErrorList);
       
   433     
       
   434     if($apiSdkRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   435     {
       
   436 	$sdk = $1;
       
   437     }
       
   438     if($apiOemRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   439     {
       
   440 	$oem = $1;
       
   441     }
       
   442     if($apiInternalRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   443     {
       
   444 	$int = $1;
       
   445     }
       
   446     if($apiPrivateRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   447     {
       
   448 	$priv = $1;
       
   449     }
       
   450     if($apiDeprecatedRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   451     {
       
   452 	$dep = $1;
       
   453     }
       
   454     if($apiObsoletedRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   455     {
       
   456 	$obs = $1;
       
   457     }
       
   458     
       
   459     if($sdk != -1)
       
   460     {
       
   461 	if($sdk < $oem || $sdk < $int || $sdk <  $priv)
       
   462 	{
       
   463 	    push(@$refToErrorList,getError($API_REL_LOGICAL_ERROR,
       
   464 					   $apiName, "SDK release"));
       
   465 	}
       
   466     }
       
   467     if($oem != -1)
       
   468     {
       
   469 	if($oem < $int || $oem <  $priv)
       
   470 	{
       
   471 	    push(@$refToErrorList,getError($API_REL_LOGICAL_ERROR,
       
   472 					   $apiName, "Oem release"));
       
   473 	}
       
   474     }
       
   475     if($int != -1)
       
   476     {
       
   477 	if($int <  $priv)
       
   478 	{
       
   479 	    push(@$refToErrorList,getError($API_REL_LOGICAL_ERROR,
       
   480 					   $apiName, "Internal release"));
       
   481 	}
       
   482     }
       
   483 
       
   484     if($dep != -1)
       
   485     {
       
   486 	if($dep < $sdk || $dep < $oem || $dep < $int || $dep <  $priv)
       
   487 	{
       
   488 	    push(@$refToErrorList,getError($API_REL_LOGICAL_ERROR,
       
   489 					   $apiName, "Deprecated release value."));
       
   490 	}
       
   491     }
       
   492     if($obs != -1)
       
   493     {
       
   494 	if($obs < $sdk || $obs < $oem || $obs < $int || $obs <  $priv || $obs < $dep)
       
   495 	{
       
   496 	    push(@$refToErrorList,getError($API_REL_LOGICAL_ERROR,
       
   497 					   $apiName, "Obsoleted release value."));
       
   498 	}
       
   499     }
       
   500 
       
   501     return  scalar(@$refToErrorList) - $errorsBeforeCheck;
       
   502 }
       
   503 
       
   504 ###########################################################################
       
   505 # Function checks that the information in the files for given release are OK.
       
   506 #
       
   507 # Params: refToErrList, checkedPlatform, apiName, fileName,apiSdkRel,apiOemRel,apiInternalRel,apiPrivateRel, 
       
   508 #         apiDeprecatedRel,apiObsoletedeRel,fileSdkRel,fileOemRel,fileInternalRel,filePrivateRel, 
       
   509 #         fileDeprecatedRel,fileObsoletedeRel
       
   510 #
       
   511 # Return:  0 no errors found
       
   512 #          > 0 amount of  errors found
       
   513 ###########################################################################
       
   514 sub checkFileRelRoadMap
       
   515 {
       
   516     my $refToErrorList = shift;
       
   517     my $checkedPlatform = shift;
       
   518     my $apiName = shift;
       
   519     my $fileName = shift;
       
   520     my $apiSdkRel = shift;
       
   521     my $apiOemRel = shift;
       
   522     my $apiInternalRel = shift;
       
   523     my $apiPrivateRel = shift;
       
   524     my $apiDeprecatedRel = shift;
       
   525     my $apiObsoletedRel = shift;
       
   526     my $fileSdkRel = shift;
       
   527     my $fileOemRel = shift;
       
   528     my $fileInternalRel = shift;
       
   529     my $filePrivateRel = shift;
       
   530     my $fileDeprecatedRel = shift;
       
   531     my $fileObsoletedRel = shift;
       
   532     
       
   533     my $apiSdk = -1;
       
   534     my $apiOem = -1;
       
   535     my $apiInt = -1;
       
   536     my $apiPriv = -1;
       
   537     my $apiDep = -1;
       
   538     my $apiObs = -1;
       
   539     my $fileSdk = -1;
       
   540     my $fileOem = -1;
       
   541     my $fileInt = -1;
       
   542     my $filePriv = -1;
       
   543     my $fileDep = -1;
       
   544     my $fileObs = -1;
       
   545 
       
   546     my $errorsBeforeCheck = scalar(@$refToErrorList);
       
   547 
       
   548     #
       
   549     # Parse the wanted platform release from all the fields.
       
   550     #
       
   551     if($apiSdkRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   552     {
       
   553 	$apiSdk = $1;
       
   554     }
       
   555     if($apiOemRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   556     {
       
   557 	$apiOem = $1;
       
   558     }
       
   559     if($apiInternalRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   560     {
       
   561 	$apiInt = $1;
       
   562     }
       
   563     if($apiPrivateRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   564     {
       
   565 	$apiPriv = $1;
       
   566     }
       
   567     if($apiDeprecatedRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   568     {
       
   569 	$apiDep = $1;
       
   570     }
       
   571     if($apiObsoletedRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   572     {
       
   573 	$apiObs = $1;
       
   574     }
       
   575     if($fileSdkRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   576     {
       
   577 	$fileSdk = $1;
       
   578     }
       
   579     if($fileOemRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   580     {
       
   581 	$fileOem = $1;
       
   582     }
       
   583     if($fileInternalRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   584     {
       
   585 	$fileInt = $1;
       
   586     }
       
   587     if($filePrivateRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   588     {
       
   589 	$filePriv = $1;
       
   590     }
       
   591     if($fileDeprecatedRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   592     {
       
   593 	$fileDep = $1;
       
   594     }
       
   595     if($fileObsoletedRel =~ /$checkedPlatform\s+([0-9]+\.[0-9]+)/)
       
   596     {
       
   597 	$fileObs = $1;
       
   598     }
       
   599 
       
   600 
       
   601     # --------------------------------------------------------
       
   602     # Actual error checking
       
   603     # --------------------------------------------------------
       
   604 
       
   605 
       
   606     #
       
   607     # Check that the file row releases make sence in logical way
       
   608     #
       
   609     my $currErrAmount = scalar(@$refToErrorList);
       
   610     if($fileSdk != -1)
       
   611     {
       
   612 	if($fileSdk < $fileOem || $fileSdk < $fileInt || $fileSdk <  $filePriv)
       
   613 	{
       
   614 	    push(@$refToErrorList,getError($FILE_REL_LOGICAL_ERROR,
       
   615 					   "$apiName :: $fileName", "SDK release \"$checkedPlatform $fileSdk\""));
       
   616 	}
       
   617     }
       
   618     if($fileOem != -1)
       
   619     {
       
   620 	if($fileOem < $fileInt || $fileOem <  $filePriv)
       
   621 	{
       
   622 	    push(@$refToErrorList,getError($FILE_REL_LOGICAL_ERROR,
       
   623 					   "$apiName :: $fileName", "Oem release \"$checkedPlatform $fileOem\""));
       
   624 	}
       
   625     }
       
   626     if($fileInt != -1)
       
   627     {
       
   628 	if($fileInt <  $filePriv)
       
   629 	{
       
   630 	    push(@$refToErrorList,getError($FILE_REL_LOGICAL_ERROR,
       
   631 					   "$apiName :: $fileName", "Internal release \"$checkedPlatform $fileInt\""));
       
   632 	}
       
   633     }
       
   634 
       
   635     if($fileDep != -1)
       
   636     {
       
   637 	if($fileDep < $fileSdk || $fileDep < $fileOem || $fileDep < $fileInt || $fileDep <  $filePriv)
       
   638 	{
       
   639 	    push(@$refToErrorList,getError($FILE_REL_LOGICAL_ERROR,
       
   640 					   "$apiName :: $fileName", "Deprecated release \"$checkedPlatform $fileDep\""));
       
   641 	}
       
   642     }
       
   643     if($fileObs != -1)
       
   644     {
       
   645 	if($fileObs < $fileSdk || $fileObs < $fileOem || $fileObs < $fileInt || $fileObs <  $filePriv || $fileObs < $fileDep)
       
   646 	{
       
   647 	    push(@$refToErrorList,getError($FILE_REL_LOGICAL_ERROR,
       
   648 					   "$apiName :: $fileName", "Obsoleted release \"$checkedPlatform $fileObs\""));
       
   649 	}
       
   650     }
       
   651 
       
   652     #
       
   653     # Check the release information for the file compared to the release information defined for the API
       
   654     #  (these are only checked, if there was no syntax errors in the release fields for the file).
       
   655     #
       
   656     if($currErrAmount == scalar(@$refToErrorList))
       
   657     {
       
   658 	#
       
   659 	# Compare the SDK information in the file against the API rel information
       
   660 	#
       
   661 	if($fileSdk != -1)
       
   662 	{
       
   663 	    # If API is not SDK => error, since file was defined as SDK
       
   664 	    if($apiSdk == -1)
       
   665 	    {
       
   666 		push(@$refToErrorList,
       
   667 		     getError($FILE_REL_LOGICAL_ERROR,
       
   668 			      "$apiName :: $fileName", "File defined as SDK, but API is not a SDK API."));	       
       
   669 	
       
   670 	    }
       
   671 	    else
       
   672 	    {
       
   673 		if($fileSdk < $apiSdk)
       
   674 		{
       
   675 		    push(@$refToErrorList,
       
   676 			 getError($FILE_REL_LOGICAL_ERROR,
       
   677 				  "$apiName :: $fileName", 
       
   678 				  "File defined as SDK from \"$checkedPlatform $fileSdk\", ",
       
   679 				  "but API defined as SDK only from \"$checkedPlatform $apiSdk\" onwards."));
       
   680 		    
       
   681 		}
       
   682 		if($apiObs != -1 && $fileSdk > $apiObs)
       
   683 		{
       
   684 		    push(@$refToErrorList,
       
   685 			 getError($FILE_REL_LOGICAL_ERROR,
       
   686 				  "$apiName :: $fileName", 
       
   687 				  "File defined as SDK from \"$checkedPlatform $fileSdk\",",
       
   688 				  "but API was defined as obsoleted \"$checkedPlatform $apiObs\" onwards."));
       
   689 		    
       
   690 		}
       
   691 	    }
       
   692 	}
       
   693 	#
       
   694 	# Compare the Oem information in the file against the API rel information
       
   695 	#
       
   696 	if($fileOem != -1)
       
   697 	{
       
   698 	    # If API is not Oem => error, since file was defined as Oem
       
   699 	    if($apiOem == -1)
       
   700 	    {
       
   701 		push(@$refToErrorList,
       
   702 		     getError($FILE_REL_LOGICAL_ERROR,
       
   703 			      "$apiName :: $fileName", "File defined as Oem, but API is not an Oem API."));	
       
   704 	    }
       
   705 	    else
       
   706 	    {
       
   707 		if($fileOem < $apiOem)
       
   708 		{
       
   709 		    push(@$refToErrorList,
       
   710 			 getError($FILE_REL_LOGICAL_ERROR,
       
   711 				  "$apiName :: $fileName", 
       
   712 				  "File defined as Oem from \"$checkedPlatform $fileOem\",",
       
   713 				  "but API defined as OEM only from \"$checkedPlatform $apiOem\" onwards."));
       
   714 		    
       
   715 		}
       
   716 		if($apiSdk != -1 && $fileOem >= $apiSdk)
       
   717 		{
       
   718 		    push(@$refToErrorList,
       
   719 			 getError($FILE_REL_LOGICAL_ERROR,
       
   720 				  "$apiName :: $fileName", 
       
   721 				  "File defined as Oem from \"$checkedPlatform $fileOem\", " ,
       
   722 				  "but API was defined as SDK from \"$checkedPlatform $apiSdk\" onwards."));
       
   723 	
       
   724 		}
       
   725 		if($apiObs != -1 && $fileOem > $apiObs)
       
   726 		{
       
   727 		    push(@$refToErrorList,
       
   728 			 getError($FILE_REL_LOGICAL_ERROR,
       
   729 				  "$apiName :: $fileName", 
       
   730 				  "File defined as Oem from \"$checkedPlatform $fileOem\", ",
       
   731 				  "but API was defined as obsoleted \"$checkedPlatform $apiObs\" onwards."));
       
   732 		}
       
   733 	    }
       
   734 	}
       
   735 	#
       
   736 	# Compare the Internal information in the file against the API rel information
       
   737 	#
       
   738 	if($fileInt != -1)
       
   739 	{
       
   740 	    # If API is not Internal => error, since file was defined as such
       
   741 	    if($apiInt == -1)
       
   742 	    {
       
   743 		push(@$refToErrorList,
       
   744 		     getError($FILE_REL_LOGICAL_ERROR,
       
   745 			      "$apiName :: $fileName", 
       
   746 			      "File defined as Internal, but API is not an Internal API."));	
       
   747 	    }
       
   748 	    else
       
   749 	    {
       
   750 		if($fileInt < $apiInt)
       
   751 		{
       
   752 		    push(@$refToErrorList,
       
   753 			 getError($FILE_REL_LOGICAL_ERROR,
       
   754 				  "$apiName :: $fileName", 
       
   755 				  "File defined as Internal from \"$checkedPlatform $fileInt\", " ,
       
   756 				  "but API defined as Internal only from \"$checkedPlatform $apiInt\" onwards."));
       
   757 		}
       
   758 		if($apiSdk != -1 && $fileInt >= $apiSdk )
       
   759 		{
       
   760 		    push(@$refToErrorList,
       
   761 			 getError($FILE_REL_LOGICAL_ERROR,
       
   762 				  "$apiName :: $fileName", 
       
   763 				  "File defined as Internal from \"$checkedPlatform $fileInt\", " ,
       
   764 				  "but API was defined as SDK from \"$checkedPlatform $apiSdk\" onwards."));
       
   765 	
       
   766 		}
       
   767 		if($apiOem != -1 && $fileInt >= $apiOem)
       
   768 		{
       
   769 		    push(@$refToErrorList,
       
   770 			 getError($FILE_REL_LOGICAL_ERROR,
       
   771 				  "$apiName :: $fileName", 
       
   772 				  "File defined as Internal from \"$checkedPlatform $fileInt\", " ,
       
   773 				  "but API was defined as Oem from \"$checkedPlatform $apiOem\" onwards."));
       
   774 	
       
   775 		}
       
   776 		if($apiObs != -1 && $fileInt > $apiObs)
       
   777 		{
       
   778 		    push(@$refToErrorList,
       
   779 			 getError($FILE_REL_LOGICAL_ERROR,
       
   780 				  "$apiName :: $fileName", 
       
   781 				  "File defined as Internal from \"$checkedPlatform $fileInt\", " ,
       
   782 				  "but API was defined as obsoleted \"$checkedPlatform $apiObs\" onwards."));
       
   783 		}
       
   784 	    }
       
   785 	}
       
   786 	#
       
   787 	# Compare the Internal information in the file against the API rel information
       
   788 	#
       
   789 	if($filePriv != -1)
       
   790 	{
       
   791 	    # If API is not Private => error, since file was defined as such
       
   792 	    if($apiPriv == -1)
       
   793 	    {
       
   794 		push(@$refToErrorList,
       
   795 		     getError($FILE_REL_LOGICAL_ERROR,
       
   796 			      "$apiName :: $fileName", 
       
   797 			      "File defined as Private, but API is not an Private API."));
       
   798 	    }
       
   799 	    else
       
   800 	    {
       
   801 		if($filePriv < $apiPriv)
       
   802 		{
       
   803 		    push(@$refToErrorList,
       
   804 			 getError($FILE_REL_LOGICAL_ERROR,
       
   805 				  "$apiName :: $fileName", 
       
   806 				  "File defined as Private from \"$checkedPlatform $filePriv\", " ,
       
   807 				  "but API defined as Private only from \"$checkedPlatform $apiPriv\" onwards."));
       
   808 		}
       
   809 		if($apiSdk != -1 && $filePriv >= $apiSdk)
       
   810 		{
       
   811 		    push(@$refToErrorList,
       
   812 			 getError($FILE_REL_LOGICAL_ERROR,
       
   813 				  "$apiName :: $fileName", 
       
   814 				  "File defined as Private from \"$checkedPlatform $filePriv\", " ,
       
   815 				  "but API was defined as SDK from \"$checkedPlatform $apiSdk\" onwards."));
       
   816 	
       
   817 		}
       
   818 		if($apiOem != -1 && $filePriv >= $apiOem)
       
   819 		{
       
   820 		    push(@$refToErrorList,
       
   821 			 getError($FILE_REL_LOGICAL_ERROR,
       
   822 				  "$apiName :: $fileName", 
       
   823 				  "File defined as Private from \"$checkedPlatform $filePriv\", " ,
       
   824 				  "but API was defined as Oem from \"$checkedPlatform $apiOem\" onwards."));
       
   825 		}
       
   826 		if($apiInt != -1 && $filePriv >= $apiInt)
       
   827 		{
       
   828 		    push(@$refToErrorList,
       
   829 			 getError($FILE_REL_LOGICAL_ERROR,
       
   830 				  "$apiName :: $fileName", 
       
   831 				  "File defined as Private from \"$checkedPlatform $filePriv\", " ,
       
   832 				  "but API was defined as Internal from \"$checkedPlatform $apiInt\" onwards."));
       
   833 		}
       
   834 		if($apiObs != -1 && $filePriv > $apiObs)
       
   835 		{
       
   836 		    push(@$refToErrorList,
       
   837 			 getError($FILE_REL_LOGICAL_ERROR,
       
   838 				  "$apiName :: $fileName", 
       
   839 				  "File defined as Private from \"$checkedPlatform $filePriv\", " ,
       
   840 				  "but API was defined as obsoleted \"$checkedPlatform $apiObs\" onwards."));
       
   841 		}
       
   842 	    }
       
   843 	}
       
   844     }
       
   845 }
       
   846 
       
   847 ################################################
       
   848 # Function adds the lib to the hash, if it contains valid data
       
   849 ################################################
       
   850 sub addLibToHash
       
   851 {
       
   852     my $refToLibHash = shift;
       
   853     my $lib = shift;
       
   854 
       
   855     if($lib !~ /^\s*N\/A\s*$/i && $lib !~ /^\s*\-\s*$/ && 
       
   856        $lib !~ /\s*\(*\s*ECOM\s*\)*\s*$/i && $lib !~ /^\s*tbd\s*$/i)
       
   857     {
       
   858 	addToHash $refToLibHash,$lib;
       
   859     }
       
   860 }
       
   861 
       
   862 ################################################
       
   863 # Function adds the dll to the hash, if it contains valid data
       
   864 ################################################
       
   865 sub addDllToHash
       
   866 {
       
   867     my $refToDllHash = shift;
       
   868     my $dll = shift;
       
   869 
       
   870     if($dll !~ /^\s*N\/A\s*$/i && $dll !~ /^\s*\-\s*$/ && 
       
   871        $dll !~ /\s*\(*\s*ECOM\s*\)*\s*$/i && $dll !~ /^\s*tbd\s*$/i)
       
   872     {
       
   873 	addToHash $refToDllHash,$dll;
       
   874     }
       
   875 }
       
   876 ###########################################################################
       
   877 # Function that reads specified platform release information from the given worksheet
       
   878 #  The information is put to the hashed passed as parameters
       
   879 ##  		if($dll !~ /^\s*N\/A\s*$/i && $dll !~ /^\s*\-\s*$/ && 
       
   880 #  		   $dll !~ /\s*\(*\s*ECOM\s*\)*\s*$/i && $dll !~ /^\s*tbd\s*$/i)
       
   881 #  		{
       
   882 #  		    addToHash $refToDllHash,$dll;
       
   883 #  		}
       
   884 
       
   885 # Params: referenceToWorksheet,wantedPlatform, wantedRelease, reftoHeaderHash,refToDllHash, refToLibHash,
       
   886 #         reftoNonSdkHeaders, [refToNonSdkLibsHash]
       
   887 #
       
   888 # Return: -
       
   889 ###########################################################################
       
   890 sub readInfo     
       
   891 {
       
   892     my $refToWorksheet = shift;
       
   893     my $plat = shift;
       
   894     my $rel = shift;
       
   895     my $reftoHeaderHash = shift;  # SDK headers
       
   896     my $refToDllHash = shift;     # SDK dll's
       
   897     my $refToLibHash = shift;     # SDK Libs
       
   898     my $refToNonSdkHeaderHash = shift;
       
   899     my $refToFutureHeaderHash = shift; # Files that are coming in future releases 
       
   900     my $refToRemovedHeaderHash = shift; # Files that are removed in previous releases 
       
   901     my $refToNonSdkLibHash = shift;    # optional, migth not exists
       
   902     my $refToFutureLibHash = shift;    
       
   903     my $refToRemovedLibHash = shift;   
       
   904     
       
   905     # check that sheet really exists (it could be missing)
       
   906     if(not defined($refToWorksheet))
       
   907     {
       
   908 	return;
       
   909     }
       
   910     # handle optionality
       
   911     if(! defined($refToNonSdkLibHash))
       
   912     {
       
   913 	my %hash;
       
   914 	$refToNonSdkLibHash = \%hash;
       
   915     }
       
   916     # ----------------------------------------------------------------  
       
   917     # look to header information
       
   918     # ----------------------------------------------------------------  
       
   919     # API Name
       
   920     # Header file(s)    (or "File(s)" in template version 1.6->)
       
   921     # Purpose	
       
   922     # Responsible
       
   923     # SDK
       
   924     # Oem               (or "Partner" in template version 1.6->1.8 or "Domain" from 1.9->)
       
   925     # Internal
       
   926     # Private   (migth be missing, as is the case in the symbian sheet)	
       
   927     # Adaptation
       
   928     # Specification
       
   929     # DLL
       
   930     # Import Lib
       
   931     # Other
       
   932     # Grouping           (or "Subsystem" in template version 1.6->)
       
   933     # Clients
       
   934     # Deprecated
       
   935     # Obsoleted          (or "Removed" in template version 1.6->)
       
   936     # Partner(s)         (Only from 1.6->)
       
   937     # Partner Contact(s) (Only from 1.6->)
       
   938     # Owner
       
   939     # Note
       
   940     my $apiNameIndex = getIndexByColName $refToWorksheet,"API Name",$globalMaxColCount;
       
   941     my $fileNameIndex = getIndexByColName $refToWorksheet,"Header file(s)",$globalMaxColCount;
       
   942     if( !defined($fileNameIndex) || $fileNameIndex < 1)
       
   943     {
       
   944 	$fileNameIndex = getIndexByColName $refToWorksheet,"File(s)",$globalMaxColCount;
       
   945     }
       
   946     my $purposeIndex = getIndexByColName $refToWorksheet,"Purpose",$globalMaxColCount;
       
   947     my $sdkIndex = getIndexByColName $refToWorksheet,"SDK",$globalMaxColCount;
       
   948     my $oemIndex = getIndexByColName $refToWorksheet,"Oem",$globalMaxColCount;
       
   949     if( !defined($oemIndex) || $oemIndex < 1)
       
   950     {
       
   951 	$oemIndex = getIndexByColName $refToWorksheet,"Partner",$globalMaxColCount;
       
   952     }
       
   953     if( !defined($oemIndex) || $oemIndex < 1)
       
   954     {
       
   955 	$oemIndex = getIndexByColName $refToWorksheet,"Domain",$globalMaxColCount;
       
   956     }
       
   957     my $internalIndex = getIndexByColName $refToWorksheet,"Internal",$globalMaxColCount;
       
   958     my $privateIndex =  getIndexByColName $refToWorksheet,"Private",$globalMaxColCount;
       
   959 
       
   960     my $dllIndex = getIndexByColName $refToWorksheet,"DLL",$globalMaxColCount;
       
   961     my $libIndex = getIndexByColName $refToWorksheet,"Import Lib",$globalMaxColCount;
       
   962     my $obsoletedIndex =  getIndexByColName $refToWorksheet,"Obsoleted",$globalMaxColCount;
       
   963     if( !defined($obsoletedIndex) || $obsoletedIndex < 1)
       
   964     {
       
   965 	$obsoletedIndex = getIndexByColName $refToWorksheet,"Removed",$globalMaxColCount;
       
   966     }
       
   967 
       
   968     my $row = 1;
       
   969     my $isAPIRow = 0;
       
   970     my $isRowWanted = 0;  # is the row part of given SDK release
       
   971     my $isAPIWanted = 0;  # is the api part of given SDK release
       
   972     my $emptyRowCount = 0;
       
   973 
       
   974     ######################################################################
       
   975     # Loop row by row until we have found $globalMaxEmptyRowCount of rows
       
   976     # empty one after each other.
       
   977     ######################################################################
       
   978     for( $row = 2;; $row++ ) 
       
   979     {	         
       
   980 	#------------------------------------------------------------
       
   981 	# Read the needed rows from the row
       
   982 	#------------------------------------------------------------
       
   983 	my $apiName   = $$refToWorksheet->Cells( $row, $apiNameIndex  )->{ 'Value' };
       
   984         my $fileName  = $$refToWorksheet->Cells( $row, $fileNameIndex  )->{ 'Value' };
       
   985         my $purpose   = $$refToWorksheet->Cells( $row, $purposeIndex  )->{ 'Value' };
       
   986         my $sdk       = $$refToWorksheet->Cells( $row, $sdkIndex  )->{ 'Value' };
       
   987         my $oem       = $$refToWorksheet->Cells( $row, $oemIndex  )->{ 'Value' };
       
   988         my $internal  = $$refToWorksheet->Cells( $row, $internalIndex  )->{ 'Value' };
       
   989         my $private;
       
   990 	if($privateIndex > 0)
       
   991 	{
       
   992 	    $private = $$refToWorksheet->Cells( $row, $privateIndex  )->{ 'Value' };
       
   993 	}
       
   994 	my $dll       = $$refToWorksheet->Cells( $row, $dllIndex  )->{ 'Value' };
       
   995 	my $lib       = $$refToWorksheet->Cells( $row, $libIndex  )->{ 'Value' };
       
   996 	my $obsoleted = $$refToWorksheet->Cells( $row, $obsoletedIndex  )->{ 'Value' };
       
   997 	
       
   998 	if($apiName =~ /^\s*Comment:/ || $purpose =~ /removed by nokia/i)
       
   999 	{
       
  1000 	    next;
       
  1001 	}
       
  1002 	
       
  1003 	#------------------------------------------------------------
       
  1004 	# We only allow $globalMaxEmptyRowCount empty rows, before we stop
       
  1005 	# handling the specific sheet
       
  1006 	#------------------------------------------------------------
       
  1007 	if(! (defined($apiName) || defined($fileName)|| defined($dll) ||
       
  1008 	      defined($lib) || defined($obsoleted)))
       
  1009 	{
       
  1010 	    $emptyRowCount++;
       
  1011 	    if($emptyRowCount > $globalMaxEmptyRowCount)
       
  1012 	    {
       
  1013 		last;
       
  1014 	    }
       
  1015 	}
       
  1016 	else
       
  1017 	{
       
  1018 	    # Was not empty line, reset counter.
       
  1019 	    $emptyRowCount = 0;
       
  1020 	}
       
  1021 	
       
  1022 	#------------------------------------------------------------
       
  1023 	# Check, if is an api line and is the API wanted
       
  1024 	#------------------------------------------------------------
       
  1025         $isAPIRow = 0;
       
  1026         if(defined($apiName) and $apiName !~ /^\s*$/)
       
  1027         {
       
  1028 	    $isAPIRow = 1;
       
  1029 	}
       
  1030 	# Check, if the line is wanted
       
  1031         $isRowWanted = isRowWanted  $plat,$rel,$isAPIRow,$sdk,$obsoleted;
       
  1032 	
       
  1033 	# Case where the api/file was not wanted 
       
  1034 	if($isRowWanted == 4)
       
  1035 	{
       
  1036 	    my $isRowWanted2 = isRowWanted  $plat,$rel,$isAPIRow,$oem,$obsoleted;
       
  1037 	    if($isRowWanted2 == 4)
       
  1038 	    {
       
  1039 		$isRowWanted2 = isRowWanted  $plat,$rel,$isAPIRow,$internal,$obsoleted;
       
  1040 	    }
       
  1041 # Do not check the private field, since those are not in epoc32/include
       
  1042 #  	    if($isRowWanted2 == 4 && $privateIndex > 0)
       
  1043 #  	    {
       
  1044 #  		$isRowWanted2 = isRowWanted  $plat,$rel,$isAPIRow,$private,$obsoleted;
       
  1045 #  	    }
       
  1046 	    
       
  1047 	    if($isRowWanted2 == 1)
       
  1048 	    {
       
  1049 		# means that the row is in the release, but non-sdk
       
  1050 		$isRowWanted = 4;
       
  1051 	    }
       
  1052 	    else
       
  1053 	    {
       
  1054 		$isRowWanted = $isRowWanted2;
       
  1055 	    }
       
  1056 	} # if($isRowWanted == 4)
       
  1057 	
       
  1058         # ----------------------------------------------------------------  
       
  1059         # Handle the API line
       
  1060         # ----------------------------------------------------------------
       
  1061         if($isAPIRow == 1 || ($isAPIRow == 0 && $isRowWanted != 1))
       
  1062         {
       
  1063 	    # Store the information in the separate variable, since we
       
  1064 	    # need the information, when handling headers (reason is that
       
  1065 	    # the headers can override the API information, but normally the 
       
  1066 	    # API information is directly the headers information)
       
  1067 	    $isAPIWanted = $isRowWanted if $isAPIRow == 1;
       
  1068 	    if($isAPIWanted == 1 && $isRowWanted != 2 && $isRowWanted != 3)
       
  1069 	    {
       
  1070 		# NOTE: in the following addings, we do not add  "N/A", "TBD","(ECOM)"
       
  1071 		#       "ECOM", "-" values
       
  1072 		#
       
  1073 		# Add the information to the hashes. They migth not all contain
       
  1074 		# information, but the called function handles the case.
       
  1075 		# (for instance there should be no headers defined)
       
  1076 		
       
  1077 		if($fileName !~ /^\s*tbd\s*$/i && $fileName !~ /^\s*DIR:/i)
       
  1078 		{
       
  1079 		    addToHash $reftoHeaderHash,$fileName;
       
  1080 		}
       
  1081 		addDllToHash $refToDllHash,$dll;
       
  1082 		addLibToHash $refToLibHash,$lib;
       
  1083 	    }
       
  1084 	    elsif($isAPIWanted == 2 || $isRowWanted == 2)
       
  1085 	    {
       
  1086 		if($fileName !~ /^\s*tbd\s*$/i && $fileName !~ /^\s*DIR:/i)
       
  1087 		{
       
  1088 		    addToHash $refToRemovedHeaderHash,$fileName;		
       
  1089 		}
       
  1090 		addLibToHash $refToRemovedLibHash,$lib;
       
  1091 	    }
       
  1092 	    elsif($isAPIWanted == 3 || $isRowWanted == 3)
       
  1093 	    {
       
  1094 		if($fileName !~ /^\s*tbd\s*$/i && $fileName !~ /^\s*DIR:/i)
       
  1095 		{
       
  1096 		    addToHash $refToFutureHeaderHash,$fileName;		
       
  1097 		}
       
  1098 		addLibToHash $refToFutureLibHash,$lib;
       
  1099 	    }
       
  1100 	    elsif($isAPIWanted != 4)
       
  1101 	    {
       
  1102 		if($fileName !~ /^\s*tbd\s*$/i && $fileName !~ /^\s*DIR:/i)
       
  1103 		{
       
  1104 		    addToHash $refToNonSdkHeaderHash,$fileName;		
       
  1105 		}
       
  1106 		addLibToHash $refToNonSdkLibHash,$lib;
       
  1107 	    }
       
  1108 	}
       
  1109         # ----------------------------------------------------------------  
       
  1110         # Handle the header line, if the API is wanted and row is wanted
       
  1111         # ----------------------------------------------------------------
       
  1112         elsif($isRowWanted == 1)
       
  1113         {
       
  1114 	    if($isAPIWanted == 1)
       
  1115 	    {
       
  1116 		# Add the information to the hashes. They migth not all contain
       
  1117 		# information, but the called function handles the case.
       
  1118 		if($fileName !~ /^\s*tbd\s*$/i && $fileName !~ /^\s*DIR:/i)
       
  1119 		{
       
  1120 		    addToHash $reftoHeaderHash,$fileName;
       
  1121 		}
       
  1122 		addDllToHash $refToDllHash,$dll;
       
  1123 		addLibToHash $refToLibHash,$lib;	    
       
  1124 	    }
       
  1125 	    # If the api row was empty => private or no release specified => do not include it anywhere.
       
  1126 	    elsif($isAPIWanted != 4)
       
  1127 	    {
       
  1128 		if($fileName !~ /^\s*tbd\s*$/i && $fileName !~ /^\s*DIR:/i)
       
  1129 		{
       
  1130 		    addToHash $refToNonSdkHeaderHash,$fileName;
       
  1131 		}
       
  1132 		addLibToHash $refToNonSdkLibHash,$lib;
       
  1133 	    }
       
  1134 	}
       
  1135         # ----------------------------------------------------------------  
       
  1136         # Handle the header line, row is not wanted
       
  1137         # ----------------------------------------------------------------
       
  1138 #  	else
       
  1139 #  	{
       
  1140 #  	    if($fileName !~ /^\s*tbd\s*$/i && $fileName !~ /^\s*DIR:/i)
       
  1141 #  	    {
       
  1142 #  		addToHash $refToNonSdkHeaderHash,$fileName;
       
  1143 #  	    }
       
  1144 #  	    addLibToHash $refToNonSdkLibHash,$lib;	    
       
  1145 #	}
       
  1146     }
       
  1147 }
       
  1148 
       
  1149 
       
  1150 ###########################################################################
       
  1151 # Function that reads all the information in the given interface sheet and checks 
       
  1152 #  for conlicts/inconsistencies.
       
  1153 # The following things are currently checked:
       
  1154 #   - The 1 row is according to the template (at least the most important fields)
       
  1155 #   - API row
       
  1156 #        *  always contains Description
       
  1157 #        * The SDK/OEM/Internal/Private/deprecated/obsoleted column values are in correct syntax
       
  1158 #        * API row has to contain at least 1 categorization
       
  1159 #        * There are no headers defined in the API row
       
  1160 #   - The lib field 
       
  1161 #        * Does not contain "dll" definitions
       
  1162 #        * No "TBD" values
       
  1163 #   - The dll field 
       
  1164 #        * Does not contain "lib" definitions
       
  1165 #        * No "TBD" values
       
  1166 #   - The header row
       
  1167 #        * exactly one file for each row
       
  1168 #        * only allowed values (no TBD for example)
       
  1169 #
       
  1170 # Params: referenceToWorksheet, Sheet name, refToConflictList
       
  1171 #
       
  1172 # Return: -
       
  1173 #
       
  1174 # The syntax of refToConflictList  is:
       
  1175 #
       
  1176 #  errorTypes:
       
  1177 #     0  = incorrect template format, details is the description as text
       
  1178 #
       
  1179 #   (
       
  1180 #    (errorType,<details, format depends on the errprType (see above))
       
  1181 #   (
       
  1182 ###########################################################################
       
  1183 sub checkConflicts
       
  1184 {
       
  1185     my $refToWorksheet = shift;
       
  1186     my $sheetName = shift;
       
  1187     my $refToErrorList = shift;
       
  1188 
       
  1189     # check that sheet really exists (it could be missing)
       
  1190     if(not defined($refToWorksheet))
       
  1191     {
       
  1192 	return;
       
  1193     }
       
  1194 
       
  1195     $sheetName =~ /([a-zA-Z0-9_ \.]+\.xls)/i;
       
  1196     $currFileName = $1;
       
  1197     # ----------------------------------------------------------------  
       
  1198     # look to header information
       
  1199     # ----------------------------------------------------------------  
       
  1200     # API Name
       
  1201     # Header file(s)    (or "File(s)" in template version 1.6->)
       
  1202     # Purpose	
       
  1203     # Responsible
       
  1204     # SDK
       
  1205     # Oem               (or "Partner" in template version 1.6->1.8 or "Domain" from 1.9->)
       
  1206     # Internal
       
  1207     # Private   (migth be missing, as is the case in the symbian sheet)	
       
  1208     # Adaptation
       
  1209     # Specification
       
  1210     # DLL
       
  1211     # Import Lib
       
  1212     # Other
       
  1213     # Grouping           (or "Subsystem" in template version 1.6->)
       
  1214     # Clients
       
  1215     # Deprecated
       
  1216     # Obsoleted          (or "Removed" in template version 1.6->)
       
  1217     # Partner(s)         (Only from 1.6->)
       
  1218     # Partner Contact(s) (Only from 1.6->)
       
  1219     # Owner
       
  1220     # Note
       
  1221     my $apiNameIndex = getIndexByColName $refToWorksheet,"API Name",$globalMaxColCount;
       
  1222     my $fileNameIndex = getIndexByColName $refToWorksheet,"Header file(s)",$globalMaxColCount;
       
  1223     if( !defined($fileNameIndex) || $fileNameIndex < 1)
       
  1224     {
       
  1225 	$fileNameIndex = getIndexByColName $refToWorksheet,"File(s)",$globalMaxColCount;
       
  1226     }
       
  1227     my $purposeIndex = getIndexByColName $refToWorksheet,"Purpose",$globalMaxColCount;
       
  1228     my $sdkIndex = getIndexByColName $refToWorksheet,"SDK",$globalMaxColCount;
       
  1229     my $oemIndex = getIndexByColName $refToWorksheet,"Oem",$globalMaxColCount;
       
  1230     if( !defined($oemIndex) || $oemIndex < 1)
       
  1231     {
       
  1232 	$oemIndex = getIndexByColName $refToWorksheet,"Partner",$globalMaxColCount;
       
  1233     }
       
  1234     if( !defined($oemIndex) || $oemIndex < 1)
       
  1235     {
       
  1236 	$oemIndex = getIndexByColName $refToWorksheet,"Domain",$globalMaxColCount;
       
  1237     }
       
  1238     my $internalIndex = getIndexByColName $refToWorksheet,"Internal",$globalMaxColCount;
       
  1239     my $privateIndex =  getIndexByColName $refToWorksheet,"Private",$globalMaxColCount;
       
  1240     my $adaptIndex = getIndexByColName $refToWorksheet,"Adaptation",$globalMaxColCount;
       
  1241     my $dllIndex = getIndexByColName $refToWorksheet,"DLL",$globalMaxColCount;
       
  1242     my $libIndex = getIndexByColName $refToWorksheet,"Import Lib",$globalMaxColCount;
       
  1243     my $deprecatedIndex =  getIndexByColName $refToWorksheet,"Deprecated",$globalMaxColCount;
       
  1244     my $obsoletedIndex =  getIndexByColName $refToWorksheet,"Obsoleted",$globalMaxColCount;
       
  1245     if( !defined($obsoletedIndex) || $obsoletedIndex < 1)
       
  1246     {
       
  1247 	$obsoletedIndex = getIndexByColName $refToWorksheet,"Removed",$globalMaxColCount;
       
  1248     }
       
  1249 
       
  1250     #############################
       
  1251     # Check, that column names are correct ones
       
  1252     #############################
       
  1253     if($apiNameIndex < 0 || $fileNameIndex < 0 || $sdkIndex < 0 || 
       
  1254        $oemIndex < 0 ||  $internalIndex < 0)
       
  1255     {
       
  1256 	push(@$refToErrorList,
       
  1257 	     getError($TEMPLATE_SYNTAX_ERROR,
       
  1258 		      "The column names are not according to the template."));
       
  1259 	return;
       
  1260     }
       
  1261 
       
  1262     my $row = 1;
       
  1263     my $isAPIRow = 0;
       
  1264     my $isRowWanted = 0;
       
  1265     my $isAPIWanted = 0;
       
  1266     my $emptyRowCount = 0;
       
  1267 
       
  1268     my $isConflict = 0;
       
  1269     my $currApiName = "";
       
  1270     my $apiSdkRel = -1;
       
  1271     my $apiOemRel = -1;
       
  1272     my $apiInternalRel = -1;
       
  1273     my $apiPrivateRel = -1;
       
  1274     my $apiDeprecatedRel = -1;
       
  1275     my $apiObsoletedRel = -1;
       
  1276 
       
  1277     my $currApiRelInfoOK = 0;
       
  1278 
       
  1279     ######################################################################
       
  1280     # Loop row by row until we have found $globalMaxEmptyRowCount of rows
       
  1281     # empty one after each other.
       
  1282     ######################################################################
       
  1283     for( $row = 2;; $row++ ) 
       
  1284     {	         
       
  1285 	$isConflict = 0;
       
  1286 
       
  1287 	#------------------------------------------------------------
       
  1288 	# Read the needed rows from the row
       
  1289 	#------------------------------------------------------------
       
  1290 	my $apiName   = $$refToWorksheet->Cells( $row, $apiNameIndex  )->{ 'Value' };
       
  1291         my $fileName    = $$refToWorksheet->Cells( $row, $fileNameIndex  )->{ 'Value' };
       
  1292         my $purpose   = $$refToWorksheet->Cells( $row, $purposeIndex  )->{ 'Value' };
       
  1293         my $sdk       = $$refToWorksheet->Cells( $row, $sdkIndex  )->{ 'Value' };
       
  1294 	my $oem       = $$refToWorksheet->Cells( $row, $oemIndex  )->{ 'Value' };
       
  1295 	my $internal  = $$refToWorksheet->Cells( $row, $internalIndex  )->{ 'Value' };
       
  1296 	my $adapt     = $$refToWorksheet->Cells( $row, $adaptIndex  )->{ 'Value' };
       
  1297 	my $dll       = $$refToWorksheet->Cells( $row, $dllIndex  )->{ 'Value' };
       
  1298 	my $lib       = $$refToWorksheet->Cells( $row, $libIndex  )->{ 'Value' };
       
  1299 	my $deprecated = $$refToWorksheet->Cells( $row, $deprecatedIndex  )->{ 'Value' };
       
  1300 	my $obsoleted = $$refToWorksheet->Cells( $row, $obsoletedIndex  )->{ 'Value' };
       
  1301 
       
  1302 	my $private;
       
  1303 	if($privateIndex > 0)
       
  1304 	{
       
  1305 	    $private   = $$refToWorksheet->Cells( $row, $privateIndex  )->{ 'Value' };
       
  1306 	}
       
  1307 	#------------------------------------------------------------
       
  1308 	# We only allow $globalMaxEmptyRowCount empty rows, before we stop
       
  1309 	# handling the specific sheet
       
  1310 	#------------------------------------------------------------
       
  1311 	if(! (defined($apiName) || defined($fileName)|| defined($dll) ||
       
  1312 	      defined($lib) || defined($obsoleted)))
       
  1313 	{
       
  1314 	    $emptyRowCount++;
       
  1315 	    if($emptyRowCount > $globalMaxEmptyRowCount)
       
  1316 	    {
       
  1317 		last;
       
  1318 	    }
       
  1319 	}
       
  1320 	else
       
  1321 	{
       
  1322 	    # Was not empty line, reset counter.
       
  1323 	    $emptyRowCount = 0;
       
  1324 	}
       
  1325 
       
  1326 	#------------------------------------------------------------
       
  1327 	# Handle API row
       
  1328 	#------------------------------------------------------------
       
  1329         $isAPIRow = 0;
       
  1330         if(defined($apiName) and $apiName !~ /^\s*$/)
       
  1331         {
       
  1332 	    $isAPIRow = 1;
       
  1333 	    $currApiRelInfoOK = 1;
       
  1334 	    $currApiName = $apiName;
       
  1335 	    # Reset the release values and set new values to them.
       
  1336 	    $apiSdkRel = -1;
       
  1337 	    $apiOemRel = -1;
       
  1338 	    $apiInternalRel = -1;
       
  1339 	    $apiPrivateRel = -1;
       
  1340 	    $apiDeprecatedRel = -1;
       
  1341 	    $apiObsoletedRel = -1;
       
  1342 	    setRelValue(\$apiSdkRel,$sdk);
       
  1343 	    setRelValue(\$apiOemRel,$oem);
       
  1344 	    setRelValue(\$apiInternalRel,$internal);
       
  1345 	    setRelValue(\$apiDeprecatedRel,$deprecated);
       
  1346 	    setRelValue(\$apiObsoletedRel,$obsoleted);
       
  1347 
       
  1348 	    if($privateIndex > -1)
       
  1349 	    {
       
  1350 		setRelValue(\$apiPrivateRel,$private);
       
  1351 	    }
       
  1352 
       
  1353 	    if($apiName =~ /^\s*Comment:/ || $purpose =~ /removed by nokia/i)
       
  1354 	    {
       
  1355 		next;
       
  1356 	    }
       
  1357 
       
  1358 	    ################################################
       
  1359             # Error checking
       
  1360 	    ################################################
       
  1361 
       
  1362 	    #
       
  1363 	    # API description is needed
       
  1364 	    #
       
  1365 	    if(!defined($purpose) || $purpose =~ /^\s*$/)
       
  1366 	    {
       
  1367 		push(@$refToErrorList,getError($API_DESC_MISSING_ERROR,
       
  1368 					       $currApiName));
       
  1369 	
       
  1370 	    }
       
  1371 
       
  1372 	    #
       
  1373 	    # Adaptation field has to be set for API
       
  1374 	    #
       
  1375 	    if($purpose !~ /is a collection api/i && defined($adapt))
       
  1376 	    {
       
  1377 		if( $adapt !~ /^\s*No\s*$/ && $adapt !~ /^\s*Yes\s*$/)
       
  1378 		{
       
  1379 		    push(@$refToErrorList,getError($API_ADAPTATION_ERROR,
       
  1380 						   $currApiName,"Value was: \"$adapt\""));
       
  1381 		}
       
  1382 	    }
       
  1383 	    #
       
  1384 	    # Check that release information is in correct format
       
  1385 	    #
       
  1386 	    my $currErrAmount = scalar(@$refToErrorList);
       
  1387 	    if(checkRel($apiSdkRel))
       
  1388 	    {
       
  1389 		push(@$refToErrorList,getError($API_REL_SYNTAX_ERROR,
       
  1390 					       $currApiName,
       
  1391 					       "SDK release value \"$apiSdkRel\""));
       
  1392 	    }
       
  1393 	    if(checkRel($apiOemRel))
       
  1394 	    {
       
  1395 		push(@$refToErrorList,getError($API_REL_SYNTAX_ERROR,
       
  1396 					       $currApiName,
       
  1397 					       "OEM release value \"$apiOemRel\""));
       
  1398 	    }   
       
  1399 
       
  1400 	    if(checkRel($apiInternalRel))
       
  1401 	    {
       
  1402 		push(@$refToErrorList,getError($API_REL_SYNTAX_ERROR,
       
  1403 					       $currApiName,
       
  1404 					       "Internal release value \"$apiInternalRel\""));
       
  1405 	    }
       
  1406 
       
  1407 	    if($privateIndex > -1 && checkRel($apiPrivateRel))
       
  1408 	    {
       
  1409 		push(@$refToErrorList,getError($API_REL_SYNTAX_ERROR,
       
  1410 					       $currApiName,
       
  1411 					       "Private release value \"$apiPrivateRel\""));
       
  1412 	    }
       
  1413 
       
  1414 	    if(checkRel($apiDeprecatedRel))
       
  1415 	    {
       
  1416 		push(@$refToErrorList,getError($API_REL_SYNTAX_ERROR,
       
  1417 					       $currApiName,
       
  1418 					       "Deprecated release value \"$apiDeprecatedRel\""));
       
  1419 	    }
       
  1420 	    if(checkRel($apiObsoletedRel))
       
  1421 	    {
       
  1422 		push(@$refToErrorList,getError($API_REL_SYNTAX_ERROR,
       
  1423 					       $currApiName,
       
  1424 					       "Obsoleted release value \"$apiObsoletedRel\""));
       
  1425 	    }
       
  1426 
       
  1427 	    #
       
  1428 	    # Check the release information for the api
       
  1429 	    #  (these are only checked, if there was no syntax errors in the release fields.
       
  1430             #
       
  1431 	    if($currErrAmount == scalar(@$refToErrorList))
       
  1432 	    {
       
  1433 		# 
       
  1434 		# Check that there is at least one release for the API.
       
  1435 		# 
       
  1436 		if($apiSdkRel == -1 && $apiOemRel == -1 && 
       
  1437 		   $apiInternalRel == -1 && $apiPrivateRel == -1 && $purpose !~ /is a collection api/i)
       
  1438 		{
       
  1439 		    push(@$refToErrorList,getError($API_REL_MISSING_ERROR,
       
  1440 						   $currApiName));
       
  1441 		    $currApiRelInfoOK = 0;
       
  1442 		}
       
  1443 		elsif($apiSdkRel == -1 && $apiOemRel == -1 && 
       
  1444 		      $apiInternalRel == -1 && $apiPrivateRel == -1)
       
  1445 		{
       
  1446 		    if(checkApiRelRoadMap($refToErrorList,"S60",$currApiName,$apiSdkRel,$apiOemRel,
       
  1447 					$apiInternalRel,$apiPrivateRel,$apiDeprecatedRel,$apiObsoletedRel))
       
  1448 		    {
       
  1449 			$currApiRelInfoOK = 0;
       
  1450 		    }
       
  1451 		    if(checkApiRelRoadMap($refToErrorList,"S90",$currApiName,$apiSdkRel,$apiOemRel,
       
  1452 					$apiInternalRel,$apiPrivateRel,$apiDeprecatedRel,$apiObsoletedRel))
       
  1453 		    {
       
  1454 			$currApiRelInfoOK = 0;
       
  1455 		    }
       
  1456 		}
       
  1457 	    }
       
  1458 	    else
       
  1459 	    {
       
  1460 		$currApiRelInfoOK = 0;
       
  1461 	    }
       
  1462 
       
  1463 	    #
       
  1464 	    # Check that there are no headers defined in the API row
       
  1465 	    #
       
  1466 	    if($fileName !~ /^\s*$/)
       
  1467 	    {
       
  1468 		push(@$refToErrorList,getError($API_HEADERS_IN_ROW_ERROR,
       
  1469 					       $currApiName));
       
  1470 	    }
       
  1471 	}
       
  1472 
       
  1473 
       
  1474 	#------------------------------------------------------------
       
  1475 	# Check the LIB and DLL fields.
       
  1476 	#------------------------------------------------------------
       
  1477 	if(defined($dll) && $dll !~ /^\s*$/ && $dll !~ /\s*\(*\s*ECOM\s*\)*\s*$/i && $dll !~ /^\s*tbd\s*$/i)
       
  1478 	{
       
  1479 	    if( $dll =~ /\.lib/i)
       
  1480 	    {
       
  1481 		push(@$refToErrorList,getError($DLL_SYNTAX_ERROR,
       
  1482 					       $currApiName,
       
  1483 					       "DLL column contains LIBs."));
       
  1484 	    }
       
  1485 	    elsif( $dll !~ /\.[dll|agt|nif|prt|csy|mdl]/i && $dll !~ /^\s*N\/A\s*$/i && $dll !~ /^\s*\-\s*$/i )
       
  1486 	    {
       
  1487 		push(@$refToErrorList,getError($DLL_SYNTAX_ERROR,
       
  1488 					       $currApiName,
       
  1489 					       "DLL column contains illegal value(s):", 
       
  1490 					       " \"$dll\""));
       
  1491 	    }
       
  1492 	}
       
  1493 	if(defined($lib) && $lib !~ /^\s*$/ && $lib !~ /\s*\(*\s*ECOM\s*\)*\s*$/i && $lib !~ /^\s*tbd\s*$/i)
       
  1494 	{
       
  1495 	    if( $lib =~ /\.dll/i)
       
  1496 	    {
       
  1497 		push(@$refToErrorList,getError($LIB_SYNTAX_ERROR,
       
  1498 					       $currApiName, 
       
  1499 					       "LIB column contains DLLs."));
       
  1500 	    }
       
  1501 	    elsif( $lib !~ /\.lib/i && $lib !~ /^\s*N\/A\s*$/i && $lib !~ /^\s*\-s*$/i )
       
  1502 	    {
       
  1503 		push(@$refToErrorList,getError($LIB_SYNTAX_ERROR,
       
  1504 					       $currApiName, 
       
  1505 					       "LIB column contains illegal values.",
       
  1506 					       "\"$lib\""));
       
  1507 	    }
       
  1508 	}
       
  1509 
       
  1510 	#------------------------------------------------------------
       
  1511 	# Check file definition rows (only if the api row was ok) 
       
  1512 	#------------------------------------------------------------
       
  1513 	if($isAPIRow == 0  && defined($fileName) && $fileName !~ /^\s*$/)
       
  1514 	{
       
  1515 	    # Set the release values for header information
       
  1516 	    my $hdrSdkRel = -1;
       
  1517 	    my $hdrOemRel = -1;
       
  1518 	    my $hdrInternalRel = -1;
       
  1519 	    my $hdrPrivateRel = -1;
       
  1520 	    my $hdrDeprecatedRel = -1;
       
  1521 	    my $hdrObsoletedRel = -1;
       
  1522 	    setRelValue(\$hdrSdkRel,$sdk);
       
  1523 	    setRelValue(\$hdrOemRel,$oem);
       
  1524 	    setRelValue(\$hdrInternalRel,$internal);
       
  1525 	    setRelValue(\$hdrDeprecatedRel,$deprecated);
       
  1526 	    setRelValue(\$hdrObsoletedRel,$obsoleted);
       
  1527 
       
  1528 	    if($privateIndex > -1)
       
  1529 	    {
       
  1530 		setRelValue(\$hdrPrivateRel,$private);
       
  1531 	    }
       
  1532 
       
  1533 	    ################################################
       
  1534 	    # Error checking
       
  1535 	    ################################################
       
  1536 	    #
       
  1537 	    # Check that only allowed values are used
       
  1538 	    if( $fileName !~ /^\s*DIR:/i  && $fileName !~ /^\s*FILE:/i &&
       
  1539 		$fileName !~ /^\s*[a-zA-Z0-9\\\/_-]+\.[h|inl|rh|hrh|loc|pan]/i && 
       
  1540 		$fileName !~ /^\s*tbd\s*$/i)
       
  1541 	    {
       
  1542 		push(@$refToErrorList,
       
  1543 		     getError($FILE_COLUMN_SYNTAX_ERROR,
       
  1544 			      $currApiName,"\"$fileName\""));
       
  1545 	    }
       
  1546 	    # 
       
  1547             # Check that there is only 1 file in the row.
       
  1548 	    #
       
  1549 	    elsif($fileName =~ /(\.[h|inl|rh|hrh|loc|pan])/ig)
       
  1550 	    {
       
  1551 		my @list;
       
  1552 		@list = ($fileName =~ /(\.[h|inl|rh|hrh|loc|pan])/ig);
       
  1553 		if(scalar(@list) > 1)
       
  1554 		{
       
  1555 		    push(@$refToErrorList,
       
  1556 			 getError($FILE_MORE_THAN_ONE_FILE_ERROR,
       
  1557 				  $currApiName, "\"$fileName\""));
       
  1558 		}
       
  1559 	    }
       
  1560 
       
  1561 	    # 
       
  1562 	    # Check that the release information is correctly defined
       
  1563 	    # (only checked, if API row was OK from that point 
       
  1564 	    if($currApiRelInfoOK == 1)
       
  1565 	    {
       
  1566 		#
       
  1567 		# Check that release information is in correct format
       
  1568 		#
       
  1569 		my $currErrAmount = scalar(@$refToErrorList);
       
  1570 		if(checkRel($hdrSdkRel))
       
  1571 		{
       
  1572 		    push(@$refToErrorList,
       
  1573 			 getError($FILE_REL_SYNTAX_ERROR,
       
  1574 				  "$currApiName :: $fileName",
       
  1575 				  "SDK release value \"$hdrSdkRel\""));
       
  1576 		}
       
  1577 		if(checkRel($hdrOemRel))
       
  1578 		{
       
  1579 		    push(@$refToErrorList,
       
  1580 			 getError($FILE_REL_SYNTAX_ERROR,
       
  1581 				  "$currApiName :: $fileName", "OEM release value \"$hdrOemRel\""));
       
  1582 		}
       
  1583 		if(checkRel($hdrInternalRel))
       
  1584 		{
       
  1585 		    push(@$refToErrorList,
       
  1586 			 getError($FILE_REL_SYNTAX_ERROR,
       
  1587 				  "$currApiName :: $fileName", "Internal release value \"$hdrInternalRel\""));
       
  1588 		}
       
  1589 
       
  1590 		if($privateIndex > -1 && checkRel($hdrPrivateRel))
       
  1591 		{
       
  1592 		    push(@$refToErrorList,
       
  1593 			 getError($FILE_REL_SYNTAX_ERROR,
       
  1594 				  "$currApiName :: $fileName", "Private release value \"$hdrPrivateRel\""));
       
  1595 		}
       
  1596 
       
  1597 		if(checkRel($hdrDeprecatedRel))
       
  1598 		{
       
  1599 		    push(@$refToErrorList,
       
  1600 			 getError($FILE_REL_SYNTAX_ERROR,
       
  1601 				  "$currApiName :: $fileName", "Deprecated release value \"$hdrDeprecatedRel\""));
       
  1602 		}
       
  1603 		if(checkRel($hdrObsoletedRel))
       
  1604 		{
       
  1605 		    push(@$refToErrorList,
       
  1606 			 getError($FILE_REL_SYNTAX_ERROR,
       
  1607 				  "$currApiName :: $fileName", "Obsoleted release value \"$hdrObsoletedRel\""));
       
  1608 		}		
       
  1609 
       
  1610 
       
  1611 		#
       
  1612 		# Check the release information for the file
       
  1613 		#  (these are only checked, if there was no syntax errors in the release fields.
       
  1614 		#
       
  1615 		if($currErrAmount == scalar(@$refToErrorList))
       
  1616 		{
       
  1617 		    checkFileRelRoadMap($refToErrorList,"S60",$currApiName,$fileName,$apiSdkRel,$apiOemRel,
       
  1618 					 $apiInternalRel,$apiPrivateRel,$apiDeprecatedRel,$apiObsoletedRel,
       
  1619 					 $hdrSdkRel,$hdrOemRel,$hdrInternalRel,$hdrPrivateRel,
       
  1620 					 $hdrDeprecatedRel,$hdrObsoletedRel);
       
  1621 		    checkFileRelRoadMap($refToErrorList,"S90",$currApiName,$fileName,$apiSdkRel,$apiOemRel,
       
  1622 					 $apiInternalRel,$apiPrivateRel,$apiDeprecatedRel,$apiObsoletedRel,
       
  1623 					 $hdrSdkRel,$hdrOemRel,$hdrInternalRel,$hdrPrivateRel,
       
  1624 					 $hdrDeprecatedRel,$hdrObsoletedRel);
       
  1625 		}
       
  1626 	    }
       
  1627 
       
  1628 	}
       
  1629     }
       
  1630 }
       
  1631 
       
  1632 
       
  1633 #################################
       
  1634 # Extracs from the given string S60 and S90 releases
       
  1635 # and puts then into the hash, if releases were found.
       
  1636 #################################
       
  1637 sub addToTypeHash
       
  1638 {
       
  1639     my $refToHash = shift;
       
  1640     my $str = shift;
       
  1641 
       
  1642     if($str=~ /S60\s+([0-9.]+)/i)
       
  1643     {
       
  1644 	$$refToHash{"s60"} = $1;
       
  1645     }
       
  1646     if($str=~ /S90\s+([0-9.]+)/i)
       
  1647     {
       
  1648 	$$refToHash{"s90"} = $1;
       
  1649     }
       
  1650 }
       
  1651 ###########################################################################
       
  1652 # Function that reads certain columns from the interface sheet to the given hash.
       
  1653 # The function is intended to be called for the c++ API definitions.
       
  1654 # For the cenrep/P&S APIs use the "readCrepInfo2"-function
       
  1655 #
       
  1656 # The format of the returned hash is:
       
  1657 #  {
       
  1658 #    <ordinal>  => 
       
  1659 #                  {
       
  1660 #                  "api_name" => <APIName>
       
  1661 #                  "api_type" => "1"    # 1 means c++, 2 means cenrep/P&S apis 
       
  1662 #                  "owner_entity" => <API owner entity>
       
  1663 #                  "files" => {<file1> => 1 ,<file2> => 1,...}
       
  1664 #                  "purpose"      => <purpose text>
       
  1665 #                  "sdk"          => { 
       
  1666 #                                    "s60" => <releaseNbr>
       
  1667 #                                    "s90" => <releaseNbr>  # Note 1:
       
  1668 #                                    }
       
  1669 #                  "partner"      => { 
       
  1670 #                                    "s60" => <releaseNbr>
       
  1671 #                                    "s90" => <releaseNbr>  # Note 1:
       
  1672 #                                    }
       
  1673 #                  "internal"     => { 
       
  1674 #                                    "s60" => <releaseNbr>
       
  1675 #                                    "s90" => <releaseNbr>  # Note 1:
       
  1676 #                                    }
       
  1677 #                  "private"      => { 
       
  1678 #                                    "s60" => <releaseNbr>
       
  1679 #                                    "s90" => <releaseNbr>  # Note 1:
       
  1680 #                                    }
       
  1681 #                  "adapt"      => "0 = no adaptation, 1 = adaptation"
       
  1682 #                  "specification" => <spec name(s)>
       
  1683 #                  "dll"       => {<dll1> => 1,<dll2> => 1,...}
       
  1684 #                  "lib"       => {<dll1> => 1,<dll2> => 1,...}
       
  1685 #                  "subsystem" => <subsystem name>
       
  1686 #                  "deprecated"   => { 
       
  1687 #                                    "s60" => <releaseNbr>
       
  1688 #                                    "s90" => <releaseNbr>  # Note 1:
       
  1689 #                          my $refToHash = shift;          }
       
  1690 #                  "removed"      => { 
       
  1691 #                                    "s60" => <releaseNbr>
       
  1692 #                                    "s90" => <releaseNbr>  # Note 1:
       
  1693 #                                    }
       
  1694 #                  "partners"         => <namesStr>
       
  1695 #                  "partner_contacts" => <namesStr>
       
  1696 #                  "base"      => "0 = not base service, 1 = is base service"
       
  1697 #                  "clients"          => <namesStr>
       
  1698 #                  "clients_org"      => <namesStr>
       
  1699 #                  "owner"        => <API owner name>
       
  1700 #                  "for_adapt_since"   => { 
       
  1701 #                                    "s60" => <releaseNbr>
       
  1702 #                                    }
       
  1703 #                  "for_adapt_deprecated"   => { 
       
  1704 #                                    "s60" => <releaseNbr>
       
  1705 #                                    }
       
  1706 #                  "for_adapt_removed"      => { 
       
  1707 #                                    "s60" => <releaseNbr>
       
  1708 #                                    }
       
  1709 #                  "extended_sdk_since"   => { 
       
  1710 #                                    "s60" => <releaseNbr>
       
  1711 #                                    }
       
  1712 #                  "extended_sdk_deprecated"   => { 
       
  1713 #                                    "s60" => <releaseNbr>
       
  1714 #                          my $refToHash = shift;          }
       
  1715 #                  "extended_sdmy $refToHash = shift;k_removed"      => { 
       
  1716 #                                    "s60" => <releaseNbr>
       
  1717 #                                    }
       
  1718 #                  }
       
  1719 # etc....
       
  1720 #  }
       
  1721 # Note the that refToHash is assumed to be an empty hash.
       
  1722 #
       
  1723 # Note 1: The S60/s90 keys are not defined, if there was no information
       
  1724 #         in the type for the API.
       
  1725 #
       
  1726 # Params: referenceToWorksheet,refToHash,defOwnerEntity,defOwner
       
  1727 #
       
  1728 # Return: -
       
  1729 ###########################################################################
       
  1730 sub readInfo2     
       
  1731 {
       
  1732     my $refToWorksheet = shift;
       
  1733     my $refToHash = shift;
       
  1734     my $defOwnerEntity = shift;
       
  1735     my $defOwner = shift;
       
  1736 
       
  1737 
       
  1738     # check that sheet really exists (it could be missing)
       
  1739     if(not defined($refToWorksheet))
       
  1740     {
       
  1741 	return;
       
  1742     }
       
  1743     
       
  1744     # getNextOrdinal
       
  1745     my $nextOrdinal = getNextOrdinal $refToHash;
       
  1746 
       
  1747     # ----------------------------------------------------------------  
       
  1748     # look to header information
       
  1749     # ----------------------------------------------------------------  
       
  1750     # API Name
       
  1751     # Header file(s)    (or "File(s)" in template version 1.6->)
       
  1752     # Purpose	
       
  1753     # Responsible
       
  1754     # SDK
       
  1755     # Oem               (or "Partner" in template version 1.6->)
       
  1756     # Internal
       
  1757     # Private   (migth be missing, as is the case in the symbian sheet)	
       
  1758     # Adaptation
       
  1759     # Specification
       
  1760     # DLL
       
  1761     # Import Lib
       
  1762     # Other
       
  1763     # Grouping           (or "Subsystem" in template version 1.6->)
       
  1764     # Clients
       
  1765     # Deprecated
       
  1766     # Obsoleted          (or "Removed" in template version 1.6->)
       
  1767     # Partner(s)         (Only from 1.6->)
       
  1768     # Partner Contact(s) (Only from 1.6->)
       
  1769     # Owner
       
  1770     # Note
       
  1771     # For Adaptation Since (only from 2.0->)
       
  1772     # For Adaptation Deprecated (only from 2.0->)
       
  1773     # For Adaptation Removed (only from 2.0->)
       
  1774     # Extended SDK Since (only from 2.0->)
       
  1775     # Extended SDK Depricated (only from 2.0->)
       
  1776     # Extended SDK Removed (only from 2.0->)
       
  1777     my $ownerNameEntityIndex = getIndexByColName $refToWorksheet,"Owner Entity",$globalMaxColCount;
       
  1778     my $apiNameIndex = getIndexByColName $refToWorksheet,"API Name",$globalMaxColCount;
       
  1779     my $fileNameIndex = getIndexByColName $refToWorksheet,"Header file(s)",$globalMaxColCount;
       
  1780     if( !defined($fileNameIndex) || $fileNameIndex < 1)
       
  1781     {
       
  1782 	$fileNameIndex = getIndexByColName $refToWorksheet,"File(s)",$globalMaxColCount;
       
  1783     }
       
  1784     my $purposeIndex = getIndexByColName $refToWorksheet,"Purpose",$globalMaxColCount;
       
  1785     my $sdkIndex = getIndexByColName $refToWorksheet,"SDK",$globalMaxColCount;
       
  1786     my $oemIndex = getIndexByColName $refToWorksheet,"Oem",$globalMaxColCount;
       
  1787     if( !defined($oemIndex) || $oemIndex < 1)
       
  1788     {
       
  1789 	$oemIndex = getIndexByColName $refToWorksheet,"Partner",$globalMaxColCount;
       
  1790     }
       
  1791     if( !defined($oemIndex) || $oemIndex < 1)
       
  1792     {
       
  1793 	$oemIndex = getIndexByColName $refToWorksheet,"Domain",$globalMaxColCount;
       
  1794     }
       
  1795     my $internalIndex = getIndexByColName $refToWorksheet,"Internal",$globalMaxColCount;
       
  1796     my $privateIndex =  getIndexByColName $refToWorksheet,"Private",$globalMaxColCount;
       
  1797     my $adaptIndex = getIndexByColName $refToWorksheet,"Adaptation",$globalMaxColCount;
       
  1798     my $specificationIndex = getIndexByColName $refToWorksheet,"Specification",$globalMaxColCount;
       
  1799     my $dllIndex = getIndexByColName $refToWorksheet,"DLL",$globalMaxColCount;
       
  1800     my $libIndex = getIndexByColName $refToWorksheet,"Import Lib",$globalMaxColCount;
       
  1801     my $ssNameIndex = getIndexByColName $refToWorksheet,"Subsystem",$globalMaxColCount;
       
  1802     if( !defined($ssNameIndex) || $ssNameIndex < 1)
       
  1803     {
       
  1804 	$ssNameIndex = getIndexByColName $refToWorksheet,"Grouping",$globalMaxColCount;
       
  1805     }
       
  1806     my $deprecatedIndex =  getIndexByColName $refToWorksheet,"Deprecated",$globalMaxColCount;
       
  1807     my $removedIndex =  getIndexByColName $refToWorksheet,"Obsoleted",$globalMaxColCount;
       
  1808     if( !defined($removedIndex) || $removedIndex < 1)
       
  1809     {
       
  1810 	$removedIndex = getIndexByColName $refToWorksheet,"Removed",$globalMaxColCount;
       
  1811     }
       
  1812     my $partnerIndex = getIndexByColName $refToWorksheet,"Partner(s)",$globalMaxColCount;
       
  1813     my $partnerContactIndex = getIndexByColName $refToWorksheet,
       
  1814                                               "Partner Contact(s)",$globalMaxColCount;
       
  1815     my $baseServiceIndex = getIndexByColName $refToWorksheet,"Base Service",$globalMaxColCount;
       
  1816     my $clientIndex = getIndexByColName $refToWorksheet,"Clients",$globalMaxColCount;
       
  1817     my $clientOrgIndex = getIndexByColName $refToWorksheet,"Client Org",$globalMaxColCount;
       
  1818     my $ownerNameIndex = getIndexByColName $refToWorksheet,"Owner",$globalMaxColCount;
       
  1819 
       
  1820     my $forAdaptationSinceIndex = getIndexByColName $refToWorksheet,"For Adaptation Since",$globalMaxColCount;
       
  1821     my $forAdaptationDeprecatedIndex = getIndexByColName $refToWorksheet,"For Adaptation Deprecated",$globalMaxColCount;
       
  1822     my $forAdaptationRemovedIndex = getIndexByColName $refToWorksheet,"For Adaptation Removed",$globalMaxColCount;
       
  1823     my $extendedSDKSinceIndex = getIndexByColName $refToWorksheet,"Extended SDK Since",$globalMaxColCount;
       
  1824     my $extendedSDKDeprecatedIndex = getIndexByColName $refToWorksheet,"Extended SDK Depricated",$globalMaxColCount;
       
  1825     my $extendedSDKRemovedIndex = getIndexByColName $refToWorksheet,"Extended SDK Removed",$globalMaxColCount;
       
  1826 
       
  1827     my $row = 1;
       
  1828     my $emptyRowCount = 0;
       
  1829 
       
  1830     ######################################################################
       
  1831     # Loop row by row until we have found $globalMaxEmptyRowCount of rows
       
  1832     # empty one after each other.
       
  1833     ######################################################################
       
  1834     my $currApiName;
       
  1835     my $currApiOrdinal;
       
  1836     for( $row = 2;; $row++ ) 
       
  1837     {	         
       
  1838 	#------------------------------------------------------------
       
  1839 	# Read the needed rows from the row
       
  1840 	#------------------------------------------------------------
       
  1841 	my $ownerEntity =  $defOwnerEntity;
       
  1842 	if($ownerNameEntityIndex > 0)
       
  1843 	{
       
  1844 	    $ownerEntity = $$refToWorksheet->Cells( $row, $ownerNameEntityIndex  )->{ 'Value' };
       
  1845 	}
       
  1846 	my $apiName   = $$refToWorksheet->Cells( $row, $apiNameIndex  )->{ 'Value' };
       
  1847         my $fileName  = $$refToWorksheet->Cells( $row, $fileNameIndex  )->{ 'Value' };
       
  1848         my $purpose   = $$refToWorksheet->Cells( $row, $purposeIndex  )->{ 'Value' };
       
  1849         my $sdk       = $$refToWorksheet->Cells( $row, $sdkIndex  )->{ 'Value' };
       
  1850 	my $oem       = $$refToWorksheet->Cells( $row, $oemIndex  )->{ 'Value' };
       
  1851 	my $internal  = $$refToWorksheet->Cells( $row, $internalIndex  )->{ 'Value' };
       
  1852 	my $private  = "";
       
  1853 	if($privateIndex > 0)
       
  1854 	{
       
  1855 	    $private = $$refToWorksheet->Cells( $row, $privateIndex  )->{ 'Value' };
       
  1856 	}
       
  1857 	my $adapt     = $$refToWorksheet->Cells( $row, $adaptIndex  )->{ 'Value' };
       
  1858 	my $specification = $$refToWorksheet->Cells( $row, $specificationIndex   )->{ 'Value' };
       
  1859 	my $dll       = $$refToWorksheet->Cells( $row, $dllIndex  )->{ 'Value' };
       
  1860 	my $lib       = $$refToWorksheet->Cells( $row, $libIndex  )->{ 'Value' };
       
  1861 	my $ssName    = $$refToWorksheet->Cells( $row, $ssNameIndex  )->{ 'Value' };
       
  1862 	my $deprecated = $$refToWorksheet->Cells( $row, $deprecatedIndex  )->{ 'Value' };
       
  1863 	my $removed    = $$refToWorksheet->Cells( $row, $removedIndex  )->{ 'Value' };
       
  1864 	my $partner = "";
       
  1865 	$partner = $$refToWorksheet->Cells( $row, $partnerIndex  )->{ 'Value' } if $partnerIndex > 0;
       
  1866 	my $partnerContact = "";
       
  1867 	$partnerContact = $$refToWorksheet->Cells( $row, $partnerContactIndex  )->{ 'Value' } if $partnerContactIndex > 0;
       
  1868 	my $baseService = "";
       
  1869 	$baseService = $$refToWorksheet->Cells( $row, $baseServiceIndex  )->{ 'Value' } if $baseServiceIndex > 0;
       
  1870 	my $client = "";
       
  1871 	$client = $$refToWorksheet->Cells( $row, $clientIndex  )->{ 'Value' } if $clientIndex > 0;
       
  1872 	my $clientOrg = "";
       
  1873 	$clientOrg = $$refToWorksheet->Cells( $row, $clientOrgIndex  )->{ 'Value' } if $clientOrgIndex > 0;
       
  1874 	my $ownerName    = $$refToWorksheet->Cells( $row, $ownerNameIndex  )->{ 'Value' };
       
  1875 
       
  1876 	my $forAdaptationSince = "";
       
  1877 	my $forAdaptationDeprecated = "";
       
  1878 	my $forAdaptationRemoved = "";
       
  1879 	my $extendedSDKSince = "";
       
  1880 	my $extendedSDKDeprecated = "";
       
  1881 	my $extendedSDKRemoved = "";
       
  1882 	# All the 6 columsn came at the same time => if 1 is present => all are present.
       
  1883 	# We just check one, since this makes the code a little bit less 
       
  1884 	if( $forAdaptationSinceIndex > 0)
       
  1885 	{
       
  1886 	    $forAdaptationSince = $$refToWorksheet->Cells( $row, $forAdaptationSinceIndex  )->{ 'Value' }  ;
       
  1887 	    $forAdaptationDeprecated = $$refToWorksheet->Cells( $row, $forAdaptationDeprecatedIndex  )->{ 'Value' };
       
  1888 	    $forAdaptationRemoved = $$refToWorksheet->Cells( $row, $forAdaptationRemovedIndex  )->{ 'Value' };
       
  1889 	    $extendedSDKSince = $$refToWorksheet->Cells( $row, $extendedSDKSinceIndex  )->{ 'Value' };
       
  1890 	    $extendedSDKDeprecated = $$refToWorksheet->Cells( $row, $extendedSDKDeprecatedIndex  )->{ 'Value' };
       
  1891 	    $extendedSDKRemoved = $$refToWorksheet->Cells( $row, $extendedSDKRemovedIndex  )->{ 'Value' };
       
  1892 	}
       
  1893 
       
  1894 	#------------------------------------------------------------
       
  1895 	# We only allow $globalMaxEmptyRowCount empty rows, before we stop
       
  1896 	# handling the specific sheet
       
  1897 	#------------------------------------------------------------
       
  1898 	if(! (defined($apiName) || defined($fileName)|| defined($dll) ||
       
  1899 	      defined($lib)))
       
  1900 	{
       
  1901 	    $emptyRowCount++;
       
  1902 	    if($emptyRowCount > $globalMaxEmptyRowCount)
       
  1903 	    {
       
  1904 		last;
       
  1905 	    }
       
  1906 	}
       
  1907 	else
       
  1908 	{
       
  1909 	    # Was not empty line, reset counter.
       
  1910 	    $emptyRowCount = 0;
       
  1911 	}
       
  1912 
       
  1913 	#------------------------------------------------------------
       
  1914 	# Check, if is an comment line. If so, then ignore line
       
  1915 	#------------------------------------------------------------
       
  1916         if(defined($apiName) and $apiName =~ /^\s*Comment:/)
       
  1917         {
       
  1918             next;
       
  1919         }
       
  1920 
       
  1921 	#------------------------------------------------------------
       
  1922 	# Check, if is an api line
       
  1923 	#------------------------------------------------------------
       
  1924         if(defined($apiName) and $apiName !~ /^\s*$/)
       
  1925         {
       
  1926 	    $currApiName = $apiName;
       
  1927 	    $currApiOrdinal = $nextOrdinal;
       
  1928 	    $nextOrdinal++;
       
  1929 
       
  1930             my %newHash;
       
  1931             $$refToHash{$currApiOrdinal} =  \%newHash;
       
  1932 
       
  1933 	    $newHash{"api_name"} = $currApiName;
       
  1934 	    $newHash{"api_type"} = 1;
       
  1935             my %hash1;
       
  1936             my %hash2;
       
  1937             my %hash3;
       
  1938             my %hash4;
       
  1939             my %hash5;
       
  1940             my %hash6;
       
  1941             my %hash7;
       
  1942             my %hash8;
       
  1943             my %hash9;
       
  1944             my %hash10;
       
  1945             my %hash11;
       
  1946             my %hash12;
       
  1947             my %hash13;
       
  1948             my %hash14;
       
  1949             my %hash15;
       
  1950             $newHash{"owner_entity"}     = $ownerEntity;
       
  1951             $newHash{"files"} = \%hash1;
       
  1952 	    $newHash{"purpose"} = $purpose;
       
  1953             $newHash{"sdk"} = \%hash4;
       
  1954 	    addToTypeHash(\%hash4,$sdk);
       
  1955             $newHash{"partner"} = \%hash5;
       
  1956 	    addToTypeHash(\%hash5,$oem);
       
  1957             $newHash{"internal"} = \%hash6;
       
  1958 	    addToTypeHash(\%hash6,$internal);
       
  1959             $newHash{"private"} = \%hash7;
       
  1960 	    addToTypeHash(\%hash7,$private);
       
  1961 	    $newHash{"adapt"} = 0;
       
  1962 	    $newHash{"adapt"} = 1 if $adapt =~ /yes/i;
       
  1963 	    $newHash{"specification"} =  $specification;
       
  1964             $newHash{"dll"} = \%hash2;
       
  1965             $newHash{"lib"} = \%hash3;
       
  1966             $newHash{"subsystem"} = $ssName;
       
  1967             $newHash{"depracated"} = \%hash8;
       
  1968 	    addToTypeHash(\%hash8,$deprecated);
       
  1969             $newHash{"removed"} = \%hash9;
       
  1970 	    addToTypeHash(\%hash9,$removed);
       
  1971 	    $newHash{"partners"} =  $partner;
       
  1972 	    $newHash{"partner_contacts"} =  $partnerContact;
       
  1973 	    $newHash{"base"} =  0;
       
  1974 	    $newHash{"base"} =  1 if $baseService =~/yes/i;
       
  1975 	    $newHash{"clients"} =  $client;
       
  1976 	    $newHash{"clients_org"} =  $clientOrg;
       
  1977             $newHash{"owner"}     = $ownerName;
       
  1978 	    $newHash{"owner"}     = $defOwner if $ownerName =~ /^\s*$/;
       
  1979 
       
  1980 	    # For adaptation
       
  1981             $newHash{"for_adapt_since"} = \%hash10;
       
  1982 	    addToTypeHash(\%hash10,$forAdaptationSince);
       
  1983             $newHash{"for_adapt_deprecated"} = \%hash11;
       
  1984 	    addToTypeHash(\%hash11,$forAdaptationDeprecated);
       
  1985             $newHash{"for_adapt_removed"} = \%hash12;
       
  1986 	    addToTypeHash(\%hash12,$forAdaptationRemoved);
       
  1987 
       
  1988 	    # extended sdk
       
  1989             $newHash{"extended_sdk_since"} = \%hash13;
       
  1990 	    addToTypeHash(\%hash13,$extendedSDKSince);
       
  1991             $newHash{"extended_sdk_deprecated"} = \%hash14;
       
  1992 	    addToTypeHash(\%hash14,$extendedSDKDeprecated);
       
  1993             $newHash{"extended_sdk_removed"} = \%hash15;
       
  1994 	    addToTypeHash(\%hash15,$extendedSDKRemoved);
       
  1995 	}
       
  1996 	#------------------------------------------------------------
       
  1997 	# Handle the files column. (ignore some special cases)
       
  1998 	#------------------------------------------------------------
       
  1999         if(defined($fileName) && $fileName !~ /^\s*DIR:/i  && 
       
  2000            $fileName !~ /^\s*FILE:/i && $fileName !~ /^\s*$/ && 
       
  2001 	   $fileName !~ /^\s*tbd\s*$/i && $fileName !~ /^\s*n\/?a\s*$/i)
       
  2002         {
       
  2003            my $refToApiHash = $$refToHash{$currApiOrdinal};
       
  2004            my $refToFilesHash = $$refToApiHash{"files"};
       
  2005            $$refToFilesHash{$fileName} = 1;
       
  2006         }
       
  2007 	#------------------------------------------------------------
       
  2008 	# Handle the dlls column. (ignore some special cases)
       
  2009 	#------------------------------------------------------------
       
  2010         if(defined($dll) && $dll !~ /^\s*$/ && $dll !~ /^\s*ECOM\s*$/i && 
       
  2011 	   $dll !~ /^\s*tbd\s*$/i && $dll !~ /^\s*n\/?a\s*$/i)
       
  2012         {
       
  2013            my $refToApiHash = $$refToHash{$currApiOrdinal};
       
  2014            my $refToDllHash = $$refToApiHash{"dll"};
       
  2015 
       
  2016            addToHash($refToDllHash,$dll);
       
  2017         }
       
  2018 	#------------------------------------------------------------
       
  2019 	# Handle the lib column. (ignore some special cases)
       
  2020 	#------------------------------------------------------------
       
  2021         if(defined($lib) && $lib !~ /^\s*$/ && $lib !~ /^\s*ECOM\s*$/i && 
       
  2022 	   $lib !~ /^\s*tbd\s*$/i && $lib !~ /^\s*n\/?a\s*$/i)
       
  2023         {
       
  2024            my $refToApiHash = $$refToHash{$currApiOrdinal};
       
  2025            my $refToLibHash = $$refToApiHash{"lib"};
       
  2026 
       
  2027            addToHash($refToLibHash,$lib);
       
  2028         }
       
  2029     }
       
  2030 }
       
  2031 
       
  2032 
       
  2033 ###########################################################################
       
  2034 # Function that reads certain columns from the interface sheet to the given hash.
       
  2035 # The function is intended to be called for the cenrep/P&S API definitions.
       
  2036 # For the c++ APIs use the "readInfo2"-function
       
  2037 #
       
  2038 # The format of the returned hash is:
       
  2039 #  {
       
  2040 #  <ordinal>  => {
       
  2041 #  
       
  2042 #                  "api_name" => <apiName>    # 1 means c++, 2 means cenrep/P&S apis 
       
  2043 #                  "api_type" => "2"    # 1 means c++, 2 means cenrep/P&S apis 
       
  2044 #                  "owner_entity" => <API owner entity>
       
  2045 #                  "uid" => <uid>
       
  2046 #                  "type" => "cenrep/ps" 
       
  2047 #                  "keys" => {<key1> => 1 ,<key12> => 1,...}
       
  2048 #                  "purpose"      => <purpose text>
       
  2049 #                  "sdk"          => { 
       
  2050 #                                    "s60" => <releaseNbr>
       
  2051 #                                    "s90" => <releaseNbr>  # Note 1:
       
  2052 #                                    }
       
  2053 #                  "partner"      => { 
       
  2054 #                                    "s60" => <releaseNbr>
       
  2055 #                                    "s90" => <releaseNbr>  # Note 1:
       
  2056 #                                    }
       
  2057 #                  "internal"     => { 
       
  2058 #                                    "s60" => <releaseNbr>
       
  2059 #                                    "s90" => <releaseNbr>  # Note 1:
       
  2060 #                                    }
       
  2061 #                  "private"      => { 
       
  2062 #                                    "s60" => <releaseNbr>
       
  2063 #                                    "s90" => <releaseNbr>  # Note 1:
       
  2064 #                                    }
       
  2065 #                  "relFeatuers" => <relatedFeature(s)>
       
  2066 #                  "subsystem" => <subsystem name>
       
  2067 #                  "deprecated"   => { 
       
  2068 #                                    "s60" => <releaseNbr>
       
  2069 #                                    "s90" => <releaseNbr>  # Note 1:
       
  2070 #                                    }
       
  2071 #                  "removed"      => { 
       
  2072 #                                    "s60" => <releaseNbr>
       
  2073 #                                    "s90" => <releaseNbr>  # Note 1:
       
  2074 #                                    }
       
  2075 #                  "partners"         => <namesStr>
       
  2076 #                  "partner_contacts" => <namesStr>
       
  2077 #                  "clients"          => <namesStr>
       
  2078 #                  "clients_org"      => <namesStr>
       
  2079 #                  "owner"        => <API owner name>
       
  2080 #                  "for_adapt_since"   => { 
       
  2081 #                                    "s60" => <releaseNbr>
       
  2082 #                                    }
       
  2083 #                  "for_adapt_deprecated"   => { 
       
  2084 #                                    "s60" => <releaseNbr>
       
  2085 #                                    }
       
  2086 #                  "for_adapt_removed"      => { 
       
  2087 #                                    "s60" => <releaseNbr>
       
  2088 #                                    }
       
  2089 #                  "extended_sdk_since"   => { 
       
  2090 #                                    "s60" => <releaseNbr>
       
  2091 #                                    }
       
  2092 #                  "extended_sdk_deprecated"   => { 
       
  2093 #                                    "s60" => <releaseNbr>
       
  2094 #                                    }
       
  2095 #                  "extended_sdk_removed"      => { 
       
  2096 #                                    "s60" => <releaseNbr>
       
  2097 #                                    }
       
  2098 #                  }
       
  2099 # etc....
       
  2100 #  }
       
  2101 # Note the that refToHash is assumed to be an empty hash.
       
  2102 #
       
  2103 # Note 1: The S60/s90 keys are not defined, if there was no information
       
  2104 #         in the type for the API.
       
  2105 #
       
  2106 # Params: referenceToWorksheet,refToHash,defOwnerEntity,defOwner
       
  2107 #
       
  2108 # Return: -
       
  2109 ###########################################################################
       
  2110 sub readCRepInfo2
       
  2111 {
       
  2112     my $refToWorksheet = shift;
       
  2113     my $refToHash = shift;
       
  2114     my $defOwnerEntity = shift;
       
  2115     my $defOwner = shift;
       
  2116 
       
  2117     # check that sheet really exists (it could be missing)
       
  2118     if(not defined($refToWorksheet))
       
  2119     {
       
  2120 	return;
       
  2121     }
       
  2122     # ----------------------------------------------------------------  
       
  2123     # getNextOrdinal
       
  2124     # ----------------------------------------------------------------  
       
  2125     my $nextOrdinal = getNextOrdinal $refToHash;
       
  2126 
       
  2127 
       
  2128     # ----------------------------------------------------------------  
       
  2129     # look to header information
       
  2130     # ----------------------------------------------------------------  
       
  2131     # API Name
       
  2132     # Uid Name
       
  2133     # Key Name
       
  2134     # Purpose	
       
  2135     # Type
       
  2136     # SDK
       
  2137     # Domain               
       
  2138     # Internal
       
  2139     # Private
       
  2140     # Subsystem
       
  2141     # Clients
       
  2142     # Client Org
       
  2143     # Deprecated
       
  2144     # Removed
       
  2145     # Related Features
       
  2146     # Partner(s)         (Only from 1.6->)
       
  2147     # Partner Contact(s) (Only from 1.6->)
       
  2148     # Owner
       
  2149     # Note
       
  2150     # For Adaptation Since (only from 2.0->)
       
  2151     # For Adaptation Deprecated (only from 2.0->)
       
  2152     # For Adaptation Removed (only from 2.0->)
       
  2153     # Extended SDK Since (only from 2.0->)
       
  2154     # Extended SDK Depricated (only from 2.0->)
       
  2155     # Extended SDK Removed (only from 2.0->)
       
  2156 
       
  2157     my $ownerNameEntityIndex = getIndexByColName $refToWorksheet,"Owner Entity",$globalMaxColCount;
       
  2158     my $apiNameIndex = getIndexByColName $refToWorksheet,"API Name",$globalMaxColCount;
       
  2159     my $uidNameIndex = getIndexByColName $refToWorksheet,"Uid Name",$globalMaxColCount;
       
  2160     my $keyNameIndex = getIndexByColName $refToWorksheet,"Key Name",$globalMaxColCount;
       
  2161     my $keyTypeIndex = getIndexByColName $refToWorksheet,"Type",$globalMaxColCount;
       
  2162     my $purposeIndex = getIndexByColName $refToWorksheet,"Purpose",$globalMaxColCount;
       
  2163     my $sdkIndex = getIndexByColName $refToWorksheet,"SDK",$globalMaxColCount;
       
  2164     my $oemIndex = getIndexByColName $refToWorksheet,"Domain",$globalMaxColCount;
       
  2165     if( !defined($oemIndex) || $oemIndex < 1)
       
  2166     {
       
  2167 	$oemIndex = getIndexByColName $refToWorksheet,"Partner",$globalMaxColCount;
       
  2168     }
       
  2169     my $internalIndex = getIndexByColName $refToWorksheet,"Internal",$globalMaxColCount;
       
  2170     my $privateIndex =  getIndexByColName $refToWorksheet,"Private",$globalMaxColCount;
       
  2171     my $ssNameIndex = getIndexByColName $refToWorksheet,"Subsystem",$globalMaxColCount;
       
  2172     if( !defined($ssNameIndex) || $ssNameIndex < 1)
       
  2173     {
       
  2174 	$ssNameIndex = getIndexByColName $refToWorksheet,"Subsystem full",$globalMaxColCount;
       
  2175     }
       
  2176     my $deprecatedIndex =  getIndexByColName $refToWorksheet,"Deprecated",$globalMaxColCount;
       
  2177     my $removedIndex =  getIndexByColName $refToWorksheet,"Removed",$globalMaxColCount;
       
  2178     my $partnerIndex = getIndexByColName $refToWorksheet,"Partner(s)",$globalMaxColCount;
       
  2179     my $partnerContactIndex = getIndexByColName $refToWorksheet,
       
  2180                                               "Partner Contact(s)",$globalMaxColCount;
       
  2181     my $clientIndex = getIndexByColName $refToWorksheet,"Clients",$globalMaxColCount;
       
  2182     my $clientOrgIndex = getIndexByColName $refToWorksheet,"Client Org",$globalMaxColCount;
       
  2183     my $ownerNameIndex = getIndexByColName $refToWorksheet,"Owner",$globalMaxColCount;
       
  2184 
       
  2185     my $forAdaptationSinceIndex = getIndexByColName $refToWorksheet,"For Adaptation Since",$globalMaxColCount;
       
  2186     my $forAdaptationDeprecatedIndex = getIndexByColName $refToWorksheet,"For Adaptation Deprecated",$globalMaxColCount;
       
  2187     my $forAdaptationRemovedIndex = getIndexByColName $refToWorksheet,"For Adaptation Removed",$globalMaxColCount;
       
  2188     my $extendedSDKSinceIndex = getIndexByColName $refToWorksheet,"Extended SDK Since",$globalMaxColCount;
       
  2189     my $extendedSDKDeprecatedIndex = getIndexByColName $refToWorksheet,"Extended SDK Depricated",$globalMaxColCount;
       
  2190     my $extendedSDKRemovedIndex = getIndexByColName $refToWorksheet,"Extended SDK Removed",$globalMaxColCount;
       
  2191 
       
  2192     my $row = 1;
       
  2193     my $emptyRowCount = 0;
       
  2194 
       
  2195     ######################################################################
       
  2196     # Loop row by row until we have found $globalMaxEmptyRowCount of rows
       
  2197     # empty one after each other.
       
  2198     ######################################################################
       
  2199     my $currApiName;
       
  2200     my $currApiOrdinal;
       
  2201     for( $row = 2;; $row++ ) 
       
  2202     {	         
       
  2203 	#------------------------------------------------------------
       
  2204 	# Read the needed rows from the row
       
  2205 	#------------------------------------------------------------
       
  2206 	my $ownerEntity =  $defOwnerEntity;
       
  2207 	if($ownerNameEntityIndex > 0)
       
  2208 	{
       
  2209 	    $ownerEntity = $$refToWorksheet->Cells( $row, $ownerNameEntityIndex  )->{ 'Value' };
       
  2210 	}
       
  2211 	my $apiName   = $$refToWorksheet->Cells( $row, $apiNameIndex  )->{ 'Value' };
       
  2212 	my $uidName   = $$refToWorksheet->Cells( $row, $uidNameIndex  )->{ 'Value' };
       
  2213         my $keyName  = $$refToWorksheet->Cells( $row, $keyNameIndex  )->{ 'Value' };
       
  2214         my $keyType  = $$refToWorksheet->Cells( $row, $keyTypeIndex  )->{ 'Value' };
       
  2215         my $purpose   = $$refToWorksheet->Cells( $row, $purposeIndex  )->{ 'Value' };
       
  2216         my $sdk       = $$refToWorksheet->Cells( $row, $sdkIndex  )->{ 'Value' };
       
  2217 	my $oem       = $$refToWorksheet->Cells( $row, $oemIndex  )->{ 'Value' };
       
  2218 	my $internal  = $$refToWorksheet->Cells( $row, $internalIndex  )->{ 'Value' };
       
  2219 	my $private = $$refToWorksheet->Cells( $row, $privateIndex  )->{ 'Value' };
       
  2220 	my $ssName    = $$refToWorksheet->Cells( $row, $ssNameIndex  )->{ 'Value' };
       
  2221 	my $deprecated = $$refToWorksheet->Cells( $row, $deprecatedIndex  )->{ 'Value' };
       
  2222 	my $removed    = $$refToWorksheet->Cells( $row, $removedIndex  )->{ 'Value' };
       
  2223 	my $partner = "";
       
  2224 	$partner = $$refToWorksheet->Cells( $row, $partnerIndex  )->{ 'Value' } if $partnerIndex > 0;
       
  2225 	my $partnerContact = "";
       
  2226 	$partnerContact = $$refToWorksheet->Cells( $row, $partnerContactIndex  )->{ 'Value' } if $partnerContactIndex > 0;
       
  2227 	my $client = "";
       
  2228 	$client = $$refToWorksheet->Cells( $row, $clientIndex  )->{ 'Value' } if $clientIndex > 0;
       
  2229 	my $clientOrg = "";
       
  2230 	$clientOrg = $$refToWorksheet->Cells( $row, $clientOrgIndex  )->{ 'Value' } if $clientOrgIndex > 0;
       
  2231 	my $ownerName    = $$refToWorksheet->Cells( $row, $ownerNameIndex  )->{ 'Value' };
       
  2232 
       
  2233 	my $forAdaptationSince = "";
       
  2234 	my $forAdaptationDeprecated = "";
       
  2235 	my $forAdaptationRemoved = "";
       
  2236 	my $extendedSDKSince = "";
       
  2237 	my $extendedSDKDeprecated = "";
       
  2238 	my $extendedSDKRemoved = "";
       
  2239 	# All the 6 columsn came at the same time => if 1 is present => all are present.
       
  2240 	# We just check one, since this makes the code a little bit less 
       
  2241 	if( $forAdaptationSinceIndex > 0)
       
  2242 	{
       
  2243 	    $forAdaptationSince = $$refToWorksheet->Cells( $row, $forAdaptationSinceIndex  )->{ 'Value' }  ;
       
  2244 	    $forAdaptationDeprecated = $$refToWorksheet->Cells( $row, $forAdaptationDeprecatedIndex  )->{ 'Value' };
       
  2245 	    $forAdaptationRemoved = $$refToWorksheet->Cells( $row, $forAdaptationRemovedIndex  )->{ 'Value' };
       
  2246 	    $extendedSDKSince = $$refToWorksheet->Cells( $row, $extendedSDKSinceIndex  )->{ 'Value' };
       
  2247 	    $extendedSDKDeprecated = $$refToWorksheet->Cells( $row, $extendedSDKDeprecatedIndex  )->{ 'Value' };
       
  2248 	    $extendedSDKRemoved = $$refToWorksheet->Cells( $row, $extendedSDKRemovedIndex  )->{ 'Value' };
       
  2249 	}
       
  2250 
       
  2251 	#------------------------------------------------------------
       
  2252 	# We only allow $globalMaxEmptyRowCount empty rows, before we stop
       
  2253 	# handling the specific sheet
       
  2254 	#------------------------------------------------------------
       
  2255 	if(! (defined($apiName) || defined($keyName)))
       
  2256 	{
       
  2257 	    $emptyRowCount++;
       
  2258 	    if($emptyRowCount > $globalMaxEmptyRowCount)
       
  2259 	    {
       
  2260 		last;
       
  2261 	    }
       
  2262 	}
       
  2263 	else
       
  2264 	{
       
  2265 	    # Was not empty line, reset counter.
       
  2266 	    $emptyRowCount = 0;
       
  2267 	}
       
  2268 
       
  2269 	#------------------------------------------------------------
       
  2270 	# Check, if is an comment line. If so, then ignore line
       
  2271 	#------------------------------------------------------------
       
  2272         if(defined($apiName) and $apiName =~ /^\s*Comment:/)
       
  2273         {
       
  2274             next;
       
  2275         }
       
  2276 
       
  2277 	#------------------------------------------------------------
       
  2278 	# Check, if is an api line
       
  2279 	#------------------------------------------------------------
       
  2280         if(defined($apiName) and $apiName !~ /^\s*$/)
       
  2281         {
       
  2282 	    $currApiName = $apiName;
       
  2283 	    $currApiOrdinal = $nextOrdinal;
       
  2284 	    $nextOrdinal++;
       
  2285 
       
  2286             my %newHash;
       
  2287             $$refToHash{$currApiOrdinal} =  \%newHash;
       
  2288 
       
  2289 	    $newHash{"api_name"} = $currApiName;
       
  2290 	    $newHash{"api_type"} = "2";
       
  2291             my %hash1;
       
  2292             my %hash2;
       
  2293             my %hash3;
       
  2294             my %hash4;
       
  2295             my %hash5;
       
  2296             my %hash6;
       
  2297             my %hash7;
       
  2298             my %hash8;
       
  2299             my %hash9;
       
  2300             my %hash10;
       
  2301             my %hash11;
       
  2302             my %hash12;
       
  2303             my %hash13;
       
  2304             my %hash14;
       
  2305             my %hash15;
       
  2306             $newHash{"owner_entity"}     = $ownerEntity;
       
  2307             $newHash{"uid"} = $uidName;
       
  2308             $newHash{"type"} = "ps";
       
  2309             $newHash{"type"} = "cenrep" if $keyType =~ /centrep/i;
       
  2310             $newHash{"keys"} = \%hash1;
       
  2311 	    $newHash{"purpose"} = $purpose;
       
  2312             $newHash{"sdk"} = \%hash4;
       
  2313 	    addToTypeHash(\%hash4,$sdk);
       
  2314             $newHash{"partner"} = \%hash5;
       
  2315 	    addToTypeHash(\%hash5,$oem);
       
  2316             $newHash{"internal"} = \%hash6;
       
  2317 	    addToTypeHash(\%hash6,$internal);
       
  2318             $newHash{"private"} = \%hash7;
       
  2319 	    addToTypeHash(\%hash7,$private);
       
  2320             $newHash{"subsystem"} = $ssName;
       
  2321             $newHash{"depracated"} = \%hash8;
       
  2322 	    addToTypeHash(\%hash8,$deprecated);
       
  2323             $newHash{"removed"} = \%hash9;
       
  2324 	    addToTypeHash(\%hash9,$removed);
       
  2325 	    $newHash{"partners"} =  $partner;
       
  2326 	    $newHash{"partner_contacts"} =  $partnerContact;
       
  2327 	    $newHash{"clients"} =  $client;
       
  2328 	    $newHash{"clients_org"} =  $clientOrg;
       
  2329             $newHash{"owner"}     = $ownerName;
       
  2330 	    $newHash{"owner"}     = $defOwner if $ownerName =~ /^\s*$/;
       
  2331 
       
  2332 	    # For adaptation
       
  2333             $newHash{"for_adapt_since"} = \%hash10;
       
  2334 	    addToTypeHash(\%hash10,$forAdaptationSince);
       
  2335             $newHash{"for_adapt_deprecated"} = \%hash11;
       
  2336 	    addToTypeHash(\%hash11,$forAdaptationDeprecated);
       
  2337             $newHash{"for_adapt_removed"} = \%hash12;
       
  2338 	    addToTypeHash(\%hash12,$forAdaptationRemoved);
       
  2339 
       
  2340 	    # extended sdk
       
  2341             $newHash{"extended_sdk_since"} = \%hash13;
       
  2342 	    addToTypeHash(\%hash13,$extendedSDKSince);
       
  2343             $newHash{"extended_sdk_deprecated"} = \%hash14;
       
  2344 	    addToTypeHash(\%hash14,$extendedSDKDeprecated);
       
  2345             $newHash{"extended_sdk_removed"} = \%hash15;
       
  2346 	    addToTypeHash(\%hash15,$extendedSDKRemoved);
       
  2347 	}
       
  2348 	#------------------------------------------------------------
       
  2349 	# Handle the files column. (ignore some special cases)
       
  2350 	#------------------------------------------------------------
       
  2351         if(defined($keyName) && $keyName !~ /^\s*$/ && 
       
  2352 	   $keyName !~ /^\s*tbd\s*$/i && $keyName !~ /^\s*n\/?a\s*$/i)
       
  2353         {
       
  2354            my $refToApiHash = $$refToHash{$currApiOrdinal};
       
  2355            my $refToKeysHash = $$refToApiHash{"keys"};
       
  2356            $$refToKeysHash{$keyName} = 1;
       
  2357         }
       
  2358     }
       
  2359 }
       
  2360 
       
  2361 ###########################################################################
       
  2362 # Function assumes that black list sheet as been given. All files that
       
  2363 # belong to the given platform and releases black list are put into the hash
       
  2364 # format of the hash:
       
  2365 #
       
  2366 # {
       
  2367 #  file1 => 1,
       
  2368 #  file2 => 1,
       
  2369 #  etc...
       
  2370 # }
       
  2371 sub readBlackList
       
  2372 {
       
  2373     my $refToWorksheet = shift;
       
  2374     my $plat = shift;
       
  2375     my $rel = shift;
       
  2376     my $refToHash = shift;
       
  2377 
       
  2378     # check that sheet really exists (it could be missing)
       
  2379     if(not defined($refToWorksheet))
       
  2380     {
       
  2381 	return;
       
  2382     }
       
  2383 
       
  2384     # ----------------------------------------------------------------  
       
  2385     # look to header information
       
  2386     # ----------------------------------------------------------------  
       
  2387     # file
       
  2388     # Since
       
  2389     my $fileNameIndex = getIndexByColName $refToWorksheet,"File/Dir",$globalMaxColCount;
       
  2390     my $sinceIndex = getIndexByColName $refToWorksheet,"Since",$globalMaxColCount;
       
  2391     my $removedIndex = getIndexByColName $refToWorksheet,"Removed",$globalMaxColCount;
       
  2392 
       
  2393     my $row = 1;
       
  2394     my $emptyRowCount = 0;
       
  2395 
       
  2396     ######################################################################
       
  2397     # Loop row by row until we have found $globalMaxEmptyRowCount of rows
       
  2398     # empty one after each other.
       
  2399     ######################################################################
       
  2400     for( $row = 2;; $row++ ) 
       
  2401     {	         
       
  2402 	#------------------------------------------------------------
       
  2403 	# Read the needed rows from the row
       
  2404 	#------------------------------------------------------------
       
  2405         my $fileName    = $$refToWorksheet->Cells( $row, $fileNameIndex  )->{ 'Value' };
       
  2406         my $since       = $$refToWorksheet->Cells( $row, $sinceIndex  )->{ 'Value' };
       
  2407 
       
  2408         my $removed     = "";
       
  2409 	if($removedIndex >= 0)
       
  2410 	{
       
  2411 	    $removed    = $$refToWorksheet->Cells( $row, $removedIndex  )->{ 'Value' };
       
  2412 	}
       
  2413 
       
  2414 	#------------------------------------------------------------
       
  2415 	# We only allow $globalMaxEmptyRowCount empty rows, before we stop
       
  2416 	# handling the specific sheet
       
  2417 	#------------------------------------------------------------
       
  2418 	if(! (defined($fileName)|| defined($since)))
       
  2419 	{
       
  2420 	    $emptyRowCount++;
       
  2421 	    if($emptyRowCount > $globalMaxEmptyRowCount)
       
  2422 	    {
       
  2423 		last;
       
  2424 	    }
       
  2425 	}
       
  2426 	else
       
  2427 	{
       
  2428 	    # Was not empty line, reset counter.
       
  2429 	    $emptyRowCount = 0;
       
  2430 	}
       
  2431 
       
  2432 	#------------------------------------------------------------
       
  2433 	# Check, if line is wanted
       
  2434 	#------------------------------------------------------------
       
  2435 	if(isRowWanted($plat,$rel,1,$since,$removed) == 1)
       
  2436 	{
       
  2437 	    addToHash $refToHash,$fileName;
       
  2438 	}
       
  2439     }    
       
  2440 }
       
  2441 1;
       
  2442