os/kernelhwsrv/halservices/hal/halcfg.pl
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 # Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 # All rights reserved.
     3 # This component and the accompanying materials are made available
     4 # under the terms of the License "Eclipse Public License v1.0"
     5 # which accompanies this distribution, and is available
     6 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 #
     8 # Initial Contributors:
     9 # Nokia Corporation - initial contribution.
    10 #
    11 # Contributors:
    12 #
    13 # Description:
    14 # hal\halcfg.pl
    15 # Check arguments and open files
    16 # 
    17 #
    18 
    19 my $nargs=scalar(@ARGV);
    20 my $xmode=0;
    21 if ($nargs==0) {
    22 	usage();
    23 }
    24 elsif ($nargs!=3 and $nargs!=4) {
    25 	die "Invalid number of arguments.  Run with no arguments for help on usage.\n";
    26 	exit;
    27 }
    28 my $arg=0;
    29 if ($nargs==4) {
    30 	if ($ARGV[$arg] eq '-x') {
    31 		$xmode=1;
    32 	} elsif ($ARGV[$arg] eq '-s') {
    33 		$xmode=2;
    34 	} elsif ($ARGV[$arg] eq '-h') {
    35 		$xmode=3;
    36 	} else {
    37 		usage();
    38 		die "Invalid 1st argument $ARGV[0]\n";
    39 	}
    40 	++$arg;
    41 }
    42 my $headerFileName=$ARGV[$arg++];
    43 my @hdr = &read_file_strip_comments($headerFileName);
    44 
    45 my $inputFileName=$ARGV[$arg++];
    46 my @input = &read_file_strip_comments($inputFileName);
    47 
    48 my $outputFileName=$ARGV[$arg++];
    49 
    50 #
    51 # Parse the header file
    52 #
    53 my $line=0;
    54 my $state=0;
    55 my $enumName;
    56 my %enumValues=();
    57 my $nextValue=0;
    58 my $bitmask=0;
    59 my %enumList=();
    60 foreach (@hdr) {
    61 	++$line;
    62 	next if (/^\s*\#/);		# ignore preprocessor directives
    63 	next if (/^\s*\/\//);	# ignore comments starting with //
    64 	next if (/^\s*$/);		# ignore blank lines
    65 	if ($state==0) {
    66 		if (/^\s*class\s+HALData\s*$/) {
    67 			$state=1;
    68 		}
    69 		if (/^\s*class\s+HALData\s*{/) {
    70 			$state=2;
    71 		}
    72 		next;
    73 	}
    74 	if ($state==1) {
    75 		if (/^\s*{/) {
    76 			$state=2;
    77 		}
    78 		next;
    79 	}
    80 	if ($state==2) {
    81 		if (/^\s*};/) {
    82 			$state=3;
    83 			last;
    84 		}
    85 		if (/^\s*enum\s+(\w+)(.*)/) {
    86 			$enumName=$1;
    87 			%enumValues=();
    88 			$nextValue=0;
    89 			$bitmask=0;
    90 			if ($2=~/^\s+{/) {
    91 				$state=5;
    92 			} else {
    93 				$state=4;
    94 			}
    95 		}
    96 		if (/^\s*bitmask\s+(\w+)(.*)/) {
    97 			$enumName=$1;
    98 			%enumValues=();
    99 			$nextValue=0;
   100 			$bitmask=1;
   101 			if ($2=~/^\s+{/) {
   102 				$state=5;
   103 			} else {
   104 				$state=4;
   105 			}
   106 		}
   107 		next;
   108 	}
   109 	if ($state==4) {
   110 		if (/^\s*{/) {
   111 			$state=5;
   112 		}
   113 		next;
   114 	}
   115 	if ($state==5) {
   116 		if (/^\s*(\w+)(.*)/) {
   117 			my $tag=$1;
   118 			my $val=0;
   119 			my $rest=$2;
   120 #			print "$tag\n$rest\n";
   121 			if ($rest=~/^\s*,/) {
   122 				$val=$nextValue;
   123 			} elsif ($rest=~/^\s*\=\s*(\d\w*)\s*\,/) {
   124 				$val=$1;
   125 				unless ($val=~/^\d*$/) {
   126 					if ($val=~/^0x(\w+)$/i) {
   127 						$val=hex $1;
   128 					} else {
   129 						undef $val;
   130 					}
   131 				}
   132 			} elsif ($rest=~/^\s*$/) {	# ignore last one
   133 				next;
   134 			} else {
   135 				undef $val;
   136 			}
   137 			unless (defined $val) {
   138 				die "Syntax error at line $line in file $headerFileName\n";
   139 			}
   140 			$nextValue=$val+1;
   141 			$enumValues{$tag}=$val;
   142 #			print "$tag=$val\n";
   143 		} elsif (/^\s*};/) {
   144 			$state=2;
   145 			if ($bitmask) {
   146 				$enumValues{'__bitmask__'}=-1;
   147 			}
   148 			my %temp=%enumValues;
   149 			$enumList{$enumName}=\%temp;
   150 		}
   151 		next;
   152 	}
   153 }
   154 if ($state!=3) {
   155 	die "Unexpected end of file in $headerFileName\n";
   156 
   157 }
   158 
   159 #	my @keys=keys %enumList;
   160 #	foreach(@keys) {
   161 #		print "enum $_\n\t{\n";
   162 #		my $ref=$enumList{$_};
   163 #		my @tags=keys(%$ref);
   164 #		foreach(@tags) {
   165 #			my $value=$$ref{$_};
   166 #			print "\t$_=$value\n";
   167 #		}
   168 #		print "\t};\n";
   169 #	}
   170 
   171 #
   172 # Build a list of properties for each attribute
   173 #
   174 my $attribref=$enumList{'TAttribute'};
   175 unless ($attribref) {
   176 	die "No TAttribute enum defined\n";
   177 }
   178 my @attribs=keys %$attribref;
   179 my %attribList;
   180 foreach (@attribs) {
   181 	my %properties;
   182 	$properties{'name'}=$_;
   183 	$properties{'ordinal'}=$$attribref{$_};
   184 	my $enum=$_;
   185 	$enum=~s/^E/T/;			# change initial E to T
   186 	if (defined $enumList{$enum}) {
   187 		my $enumRef=$enumList{$enum};
   188 		$properties{'enum'}=$enumRef;
   189 		if (defined $$enumRef{'__bitmask__'}) {
   190 			$properties{'bitmask'}=1;
   191 		}
   192 	}
   193 	$attribList{$_}=\%properties;
   194 }
   195 
   196 my $attpropref=$enumList{'TAttributeProperty'};
   197 my %PropTable;
   198 if ($xmode) {
   199 	unless ($attpropref) {
   200 		die "No TAttributeProperty enum defined\n";
   201 	}
   202 
   203 	my @attprops=keys(%$attpropref);
   204 	foreach (@attprops) {
   205 		if (/^E(\w+)$/) {
   206 			my $propname=lc $1;
   207 			$PropTable{$propname}='HAL::'.$_;
   208 		} else {
   209 			die "Invalid attribute property $_\n";
   210 		}
   211 	}
   212 }
   213 my @PropTableKeys=keys %PropTable;
   214 
   215 
   216 #
   217 # Parse the input file
   218 #
   219 $line=0;
   220 foreach (@input) {
   221 	++$line;
   222 	next if (/^\s*\/\//);	# ignore comments starting with //
   223 	next if (/^\s*$/);		# ignore blank lines
   224 	if (/^\s*(\w+)\s*(.*)/) {
   225 		my $attrib=$1;
   226 		my $rest=$2;
   227 		my $propRef=$attribList{$attrib};
   228 		unless (defined $propRef) {
   229 			die "Unrecognised attribute at line $line in file $inputFileName\n";
   230 		}
   231 #		print "$rest\n";
   232 		if ($rest=~/^\:\s*(.*)/) {	# attribute properties follow
   233 			if (!$xmode) {
   234 				die "Line $line: Properties not permitted without -x option\n";
   235 			}
   236 			$rest=$1;
   237 #			print "$rest\n";
   238 			while ($rest=~/^(\w+)\s*(.*)/) {
   239 				my $prop=lc $1;
   240 				$rest=$2;
   241 #				print "$rest\n";
   242 				my $error=matchabbrev(\$prop, \@PropTableKeys);
   243 				if ($error) {
   244 					die "$error property $prop at line $line in file $inputFileName\n";
   245 				}
   246 				$$propRef{$prop}=1;
   247 				if ($rest=~/^,\s*(.*)/) {
   248 					$rest=$1;
   249 				} elsif ($rest=~/^=\s*(.*)/) {
   250 					$rest=$1;
   251 					last;
   252 				} else {
   253 					die "Syntax error at line $line in file $inputFileName\n";
   254 				}
   255 			}
   256 		} elsif ($rest=~/^=\s*(.*)/) {
   257 			$rest=$1				# attribute value follows
   258 		} else {
   259 			die "Invalid attribute specification at line $line in file $inputFileName\n";
   260 		}
   261 #		print "$rest\n";
   262 		if ($xmode) {
   263 #			print "$rest\n";
   264 			if ($rest=~/^((\w|:)+)/) {
   265 				$$propRef{'value'}=$1;
   266 			} else {
   267 				die "Invalid function name $rest at line $line in file $inputFileName\n";
   268 			}
   269 		} elsif (defined $$propRef{'bitmask'}) {		# bitmask value
   270 			my $enumRef=$$propRef{'enum'};
   271 			my @keys=keys %$enumRef;
   272 			my $val=0;
   273 			while ($rest=~/^(\w+)\s*(.*)/) {
   274 				my $bitmaskKey=$1;
   275 				$rest=$2;
   276 				if ($bitmaskKey eq '0' or lc($bitmaskKey) eq 'none') {
   277 					last if ($val==0);
   278 					die "Inconsistent bit mask values at line $line in file $inputFileName\n";
   279 				}
   280 				my $error=matchabbrev(\$bitmaskKey,\@keys);
   281 				if ($error) {
   282 					die "$error bit value $bitmaskKey at line $line in file $inputFileName\n";
   283 				}
   284 				$val |= $$enumRef{$bitmaskKey};
   285 				if ($rest=~/^\+\s*(.*)/) {
   286 					$rest=$1;
   287 				} elsif ($rest=~/^\s*$/) {
   288 					last;
   289 				} else {
   290 					die "Syntax error at line $line in file $inputFileName\n";
   291 				}
   292 			}
   293 			$$propRef{'value'}=$val;
   294 		} elsif (defined $$propRef{'enum'} and $rest!~/^\d/) {	# enum value
   295 			my $enumRef=$$propRef{'enum'};
   296 			my @keys=keys %$enumRef;
   297 			if ($rest=~/^(\w+)\s*$/) {
   298 				my $enumKey=$1;
   299 				my $error=matchabbrev(\$enumKey,\@keys);
   300 				if ($error) {
   301 					die "$error enumeration value $enumKey at line $line in file $inputFileName\n";
   302 				}
   303 				$$propRef{'value'}=$$enumRef{$enumKey};
   304 			} else {
   305 				die "Invalid enum value $rest at line $line in file $inputFileName\n";
   306 			}
   307 		} elsif ($rest=~/^(\-?\d\w*)\s*$/) {		# numeric value (decimal or hex) with optional -ve sign
   308 			my $val=$1;
   309 			unless ($val=~/^(\-?\d)\d*$/) {         # First character should be an optional -ve sign followed by only digits
   310 				if ($val=~/^(\-?)0x(\w+)$/i) {       # First character should be an optional -ve sign followed by only alphanumerics 
   311 					my $sign=$1;
   312 					$val=hex $2;
   313 					if ($sign  eq '-') {
   314 					  $val=-$val;
   315 					} 
   316 				} else {
   317 					undef $val;
   318 				}
   319 			}
   320 			unless (defined $val) {
   321 				die "Invalid attribute value $1 at line $line in file $inputFileName\n";
   322 			}
   323 			$$propRef{'value'}=$val;
   324 		} else {								# invalid
   325 			die "Invalid attribute value at line $line in file $inputFileName\n";
   326 		}
   327 	} else {
   328 		die "Unrecognised attribute at line $line in file $inputFileName\n";
   329 	}
   330 }
   331 
   332 #	foreach (@attribs) {
   333 #		my $propRef=$attribList{$_};
   334 #		if (defined $$propRef{'value'}) {
   335 #			print "Attribute $_:\n";
   336 #			my @keys=keys %$propRef;
   337 #			foreach (@keys) {
   338 #				print "\t$_=$$propRef{$_}\n";
   339 #			}
   340 #		}
   341 #	}
   342 
   343 #
   344 # Sort attributes by ordinal
   345 #
   346 my @AttribsByOrdinal;
   347 foreach (@attribs) {
   348 	my $propRef=$attribList{$_};
   349 	my $ordinal=$$propRef{'ordinal'};
   350 	$AttribsByOrdinal[$ordinal]=$propRef;
   351 }
   352 my $nAttribs=scalar(@AttribsByOrdinal);
   353 
   354 #
   355 # Generate the output file
   356 #
   357 
   358 open OUT, ">$outputFileName" or die "Cannot open output file $outputFileName\n";
   359 
   360 #	binmode OUT;
   361 #	my $i=0;
   362 #	while ($i<$nAttribs) {
   363 #		my $value=0x80000000;
   364 #		my $propRef=$AttribsByOrdinal[$i];
   365 #		if (defined $$propRef{'value'}) {
   366 #			$value=$$propRef{'value'};
   367 #		}
   368 #		++$i;
   369 #		my $b3=($value>>24)&0xff;
   370 #		my $b2=($value>>16)&0xff;
   371 #		my $b1=($value>>8)&0xff;
   372 #		my $b0=$value&0xff;
   373 #		my $b0123=chr $b0;
   374 #		$b0123.=chr $b1;
   375 #		$b0123.=chr $b2;
   376 #		$b0123.=chr $b3;
   377 #		my $writeres=syswrite OUT, $b0123, 4;
   378 #		if ($writeres != 4) {
   379 #			die "Error writing output file $outputFileName\n";
   380 #		}
   381 #	}
   382 #	exit;
   383 
   384 my @splitName=split /(:|\\)/, $outputFileName;
   385 my $rootName=pop @splitName;
   386 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
   387 #print "\n$hour:$min:$sec $mday-$mon-$year wday=$wday, yday=$yday, isdst=$isdst\n\n";
   388 $year+=1900;
   389 
   390 print OUT "// $rootName\n";
   391 print OUT "//\n";
   392 print OUT "// Copyright (c) 1999-$year Nokia Corporation and/or its subsidiary(-ies).";
   393 print OUT "// All rights reserved.\n";
   394 print OUT "//\n";
   395 if ($xmode!=2) {
   396 	print OUT "// GENERATED FILE - DO NOT EDIT\n";
   397 	print OUT "//\n";
   398 }
   399 print OUT "\n";
   400 print OUT "#include <kernel/hal_int.h>\n";
   401 if ($xmode==0) {
   402 	print OUT <<EOF;
   403 #ifdef __CW32__
   404 // CodeWarrior requires EXPORT_C on the definiton here, as well as the declaration (in hal_int.h)
   405 EXPORT_C const TInt HalInternal::InitialValue[]=
   406 #else
   407 EXPORT_D const TInt HalInternal::InitialValue[]=
   408 #endif
   409 	{
   410 EOF
   411 
   412 	my $i=0;
   413 	while ($i<$nAttribs) {
   414 		my $propRef=$AttribsByOrdinal[$i];
   415 		++$i;
   416 		my $separator=($i<$nAttribs)?',':'';
   417 		my $name=$$propRef{'name'};
   418 		my $value=0;
   419 		if (defined $$propRef{'value'}) {
   420 			$value=$$propRef{'value'};
   421 		}
   422 		print OUT "\t$value$separator\t\t// $name\n";
   423 	}
   424 	print OUT "\t};\n";
   425 } elsif ($xmode==1) {
   426 	print OUT "\n";
   427 	my $i=0;
   428 	while ($i<$nAttribs) {
   429 		my $propRef=$AttribsByOrdinal[$i];
   430 		++$i;
   431 		my $name=$$propRef{'name'};
   432 		my $imp=$$propRef{'value'};
   433 		if ($imp=~/^\s*0\s*$/) {
   434 			undef $imp;
   435 		}
   436 		if (defined $imp) {
   437 			print OUT "GLREF_C TInt $imp(TInt, TInt, TBool, TAny*);\t// $name\n";
   438 		}
   439 	}
   440 	print OUT "\n";
   441 	print OUT "const TUint8 HalInternal::Properties[]=\n";
   442 	print OUT "\t{\n";
   443 	$i=0;
   444 	while ($i<$nAttribs) {
   445 		my $propRef=$AttribsByOrdinal[$i];
   446 		++$i;
   447 		my $separator=($i<$nAttribs)?',':'';
   448 		my $properties="";
   449 		my $name=$$propRef{'name'};
   450 		if (defined $$propRef{'value'}) {
   451 			$properties=$PropTable{'valid'};
   452 			my @keys=keys(%$propRef);
   453 			foreach (@keys) {
   454 				my $pConst=$PropTable{$_};
   455 				if (defined $pConst) {
   456 					$properties.="|$pConst";
   457 				}
   458 			}
   459 		}
   460 		if ($properties=~/^\s*$/) {
   461 			$properties='0';
   462 		}
   463 		print OUT "\t$properties$separator\t\t// $name\n";
   464 	}
   465 	print OUT "\t};\n";
   466 	print OUT "\n#if 0\n";
   467 	print OUT "const TInt HalInternal::Offset[]=\n";
   468 	print OUT "\t{\n";
   469 	my $memOffset=0;
   470 	$i=0;
   471 	while ($i<$nAttribs) {
   472 		my $propRef=$AttribsByOrdinal[$i];
   473 		++$i;
   474 		my $separator=($i<$nAttribs)?',':'';
   475 		my $name=$$propRef{'name'};
   476 		my $imp=$$propRef{'value'};
   477 		if ($imp=~/^\s*0\s*$/) {
   478 			print OUT "\t$memOffset$separator\t\t// $name\n";
   479 			$memOffset+=4;
   480 		} else {
   481 			print OUT "\t-1$separator\t\t// $name\n";
   482 		}
   483 	}
   484 	print OUT "\t};\n";
   485 	print OUT "\n#endif\n";
   486 	print OUT "const TInt HalInternal::HalDataSize=$memOffset;\n";
   487 	print OUT "\n";
   488 	print OUT "const THalImplementation HalInternal::Implementation[]=\n";
   489 	print OUT "\t{\n";
   490 	$i=0;
   491 	while ($i<$nAttribs) {
   492 		my $propRef=$AttribsByOrdinal[$i];
   493 		++$i;
   494 		my $separator=($i<$nAttribs)?',':'';
   495 		my $name=$$propRef{'name'};
   496 		my $imp=$$propRef{'value'};
   497 		if (!defined $imp or $imp=~/^\s*0\s*$/) {
   498 			$imp='NULL';
   499 		}
   500 		print OUT "\t$imp$separator\t\t// $name\n";
   501 	}
   502 	print OUT "\t};\n";
   503 } elsif ($xmode==2) {
   504 	print OUT "\n";
   505 	$i=0;
   506 	while ($i<$nAttribs) {
   507 		my $propRef=$AttribsByOrdinal[$i];
   508 		++$i;
   509 		my $name=$$propRef{'name'};
   510 		my $imp=$$propRef{'value'};
   511 		if ($imp=~/^\s*0\s*$/) {
   512 			undef $imp;
   513 		}
   514 		my $setarg=' /*aSet*/';
   515 		if (defined $$propRef{'settable'}) {
   516 			$setarg=' aSet';
   517 		}
   518 		if (defined $imp) {
   519 			print OUT "// $name\n";
   520 			print OUT "TInt $imp(TInt /*aDeviceNumber*/, TInt /*aAttrib*/, TBool$setarg, TAny* aInOut)\n";
   521 			print OUT "\t{\n";
   522 			print OUT "\treturn KErrNone;\n";
   523 			print OUT "\t}\n";
   524 			print OUT "\n";
   525 		}
   526 	}
   527 	print OUT "\n";
   528 } elsif ($xmode==3) {
   529 	my $hdrprot='__'.uc $rootName.'__';
   530 	$hdrprot=~s/\./_/;
   531 	print OUT "\n";
   532 	print OUT "#ifndef $hdrprot\n";
   533 	print OUT "#define $hdrprot\n";
   534 	$i=0;
   535 	while ($i<$nAttribs) {
   536 		my $propRef=$AttribsByOrdinal[$i];
   537 		++$i;
   538 		my $name=$$propRef{'name'};
   539 		my $imp=$$propRef{'value'};
   540 		if ($imp=~/^\s*0\s*$/) {
   541 			undef $imp;
   542 		}
   543 		if (defined $imp) {
   544 			print OUT "GLREF_C TInt $imp(TInt, TInt, TBool, TAny*);\t// $name\n";
   545 		}
   546 	}
   547 	print OUT "\n";
   548 	print OUT "#endif\n";
   549 }
   550 
   551 print OUT "\n";
   552 
   553 exit;
   554 
   555 # END OF MAIN
   556 
   557 sub matchabbrev($$) {
   558 	my ($inref, $lref)=@_;
   559 	my @matches=grep(/$$inref/i,@$lref);
   560 	my $nmatches=scalar(@matches);
   561 	if ($nmatches==0) {
   562 		return "Unknown";
   563 	} elsif ($nmatches>1) {
   564 		my @xmatches=grep(/^$$inref$/i,@matches);
   565 		if (scalar(@xmatches)!=1) {
   566 			return "Ambiguous";
   567 		} else {
   568 			$$inref=$xmatches[0];
   569 			return undef;
   570 		}
   571 	} else {
   572 		$$inref=$matches[0];
   573 		return undef;
   574 	}
   575 }
   576 
   577 sub read_file_strip_comments($) {
   578 	my ($filename) = @_;
   579 	open IN, $filename or die "Cannot read file $filename\n";
   580 	my $in;
   581 	while (<IN>) {
   582 		$in .= $_;
   583 	}
   584 	close IN;
   585 
   586 	# Strip comments
   587 	$in =~ s/\/\*(.*?)\*\//\n/gms;
   588 	$in =~ s/\/\/(.*?)\n/\n/gms;
   589 
   590 	return split(/(\n)/, $in);
   591 }
   592 
   593 sub usage() {
   594 	print
   595 		"\n",
   596 		"halcfg.pl is a perl script that is used by the build system to generate the\n",
   597 		"C++ source files from the Config and Values files.\n",
   598 		"\n",
   599 		"There are four modes in which the Perl script halcfg.pl can be used.\n",
   600 		"\n",
   601 		"\"perl halcfg.pl hal_data.h values.hda values.cpp\"\n",
   602 		"\n",
   603 		"takes the values.hda text file and generates a table of initial values for\n",
   604 		"items stored by the HAL.\n",
   605 		"\n",
   606 		"\"perl halcfg.pl -x hal_data.h config.hcf config.cpp\"\n",
   607 		"\n",
   608 		"generates three tables:\n",
   609 		"\n",
   610 		"  - the properties, i.e. whether valid and/or writable, for each item\n",
   611 		"\n",
   612 		"  - the offset of each item within the DllGlobal block\n",
   613 		"\n",
   614 		"  - the function implementing each item, for derived attributes. ie. those\n",
   615 		"    attributes that are not simply stored by the HAL.\n",
   616 		"\n",
   617 		"\"perl halcfg.pl -s hal_data.h config.hcf source.cpp\"\n",
   618 		"\n",
   619 		"generates a source file containing skeleton code for the implementation of the\n",
   620 		"accessor function for each derived attribute\n",
   621 		"\n",
   622 		"\"perl halcfg.pl -h hal_data.h config.hcf header.h\"\n",
   623 		"\n",
   624 		"generates a header file containing prototypes for the accessor functions for\n",
   625 		"each derived attribute\n",
   626 		"\n",
   627 		"Note that the header file hal_data.h containing the attributes and values used\n",
   628 		"by the HAL is passed on all calls to the perl script.\n";
   629 
   630 	exit;
   631 }