halservices/hal/halcfg.pl
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 }