File: [Development] / projects / ogl-sample / main / tools / libspec / libspec.pm (download)
Revision 1.3, Wed Apr 26 05:54:00 2000 UTC (17 years, 6 months ago) by ljp
Branch: MAIN
CVS Tags: tested_with_xf86_3_3 Changes since 1.2: +50 -3
lines
Specfile updates for SI (not registry), add a few misc. files that
weren't exported from the internal source tree.
|
#
# License Applicability. Except to the extent portions of this file are
# made subject to an alternative license as permitted in the SGI Free
# Software License B, Version 1.1 (the "License"), the contents of this
# file are subject only to the provisions of the License. You may not use
# this file except in compliance with the License. You may obtain a copy
# of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
# Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
#
# http://oss.sgi.com/projects/FreeB
#
# Note that, as provided in the License, the Software is distributed on an
# "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
# DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
# CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
# PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
#
# Original Code. The Original Code is: OpenGL Sample Implementation,
# Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
# Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
# Copyright in any portions created by third parties is as indicated
# elsewhere herein. All Rights Reserved.
#
# Additional Notice Provisions: The application programming interfaces
# established by SGI in conjunction with the Original Code are The
# OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
# April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
# 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
# Window System(R) (Version 1.3), released October 19, 1998. This software
# was created using the OpenGL(R) version 1.2.1 Sample Implementation
# published by SGI, but has not been independently verified as being
# compliant with the OpenGL(R) version 1.2.1 Specification.
#
#
# NAME:
# libspec.pm -- perl script to parse .spec files
#
# DESCRIPTION:
# This perl script parses the .spec format for each function
# interface, generates values into global veriables, and then calls
# the user's main() function to generate output. The main() function
# grabs the appropriate info from the global variables.
# The user can also specify an initialize() and finalize() function,
# and a passthru() function used for data to be passed through
# intact.
#
# AUTHORS:
# Initial authors of awk script:
# Dave Ciemiewicz (ciemo)
# Gary Tarolli (gt)
# David Mott (mott) - for gldebug
# tweeked by numerous people in the OpenGL teams
# Ported to perl:
# George Kyriazis (kyriazis)
#
#
# $Date$ $Revision$
# $Header: //depot/main/tools/libspec/libspec.pm#7 $
#
use Getopt::Long;
use File::Basename;
use libspeccutils;
$validDirections{"in"} = 1;
$validDirections{"out"} = 1;
$validDirections{"inout"} = 1;
$validTransferTypes{"value"} = 1;
$validTransferTypes{"reference"} = 1;
$validTransferTypes{"array"} = 1;
#
# strip comments
#
sub stripcomments {
my ($in) = @_;
$in =~ s/^[ \t]*\$//; # remove empty lines
$in =~ s/[ \t]*\#.*$//; # comments at end of line (& comment lines)
if ($in =~ /^$/) { return ""; }
$in;
}
#
# canonicalize pathname, according to the operating system's liking
#
sub canonicalizePathname {
my ($filename) = @_;
my ($path) = $ENV{PATH};
if ($path =~ m/\\/) {
# OS is windows (replace slashes with backslashes)
$filename =~ s/\//\\/;
} else {
# OS is unix (replaces backslashes with slashes)
$filename =~ s/\\/\//;
}
return $filename;
}
#
# output copyright message
#
sub outputCopyright {
my ($type) = @_;
my ($message);
$message = 'THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT';
open(COPYRIGHT, $optionvars{"copyright"}) ||
die("Cannot open copyright file\n");
print "\n";
if ($type eq "c") {
print "/*\n";
while(<COPYRIGHT>) {
print "** ", $_;
}
print "*/\n\n";
print "/* ", $message, " */\n\n";
}
if ($type eq "sh") {
print "#\n";
while(<COPYRIGHT>) {
print "# ", $_;
}
print "#\n\n";
print "# ", $message, "\n\n";
}
close(COPYRIGHT);
}
#
# print a read error message fo the file/linenumber specified
#
sub readError {
my ($arg1, $arg2, $arg3) = @_;
if ($arg2 eq "") {
error($arg1);
return;
}
if ($arg3 eq "") {
error("file " . $arg1 . ": " . $arg2);
return;
}
error("file " . $arg1 . ", line " . $arg2 . ": " . $arg3);
}
#
# print an error message
#
sub error {
my ($err) = @_;
print STDERR $err . "\n";
}
#
# reset parseing states to false
#
# The parsing routines will indicate errors by setting one of those flags
#
sub _resetParseStates {
$parseErrorOccured = 0;
$parsedPrototype = 0;
$parsedReturn = 0;
}
#
# returns true if argument is a constant (decimal) value and not an identifier
#
sub isConstant {
my ($string) = @_;
if ($string =~ /^[0-9]+$/) {
return 1;
} else {
return 0;
}
}
##############################################################################
#
# Wire Functions
#
##############################################################################
##############################################################################
#
# NAME
# _readWireFile()
#
# DESCRIPTION
# Create the wire map by reading the specified wire file. The
# format of the file is simple: 2 columns, left column is the
# DeclaredType of the parameter,the right column is the wire
# format for the parameter.
#
##############################################################################
sub _readWireFile {
my ($WireFile, $typeMapFileWithSlashes);
my (@f);
$typeMapFileWithSlashes = $typeMapFile;
$typeMapFileWithSlashes =~ s/\\/\//g;
$WireFile = dirname($typeMapFileWithSlashes) . "/spec2wire.map";
$WireFile = canonicalizePathname($WireFile);
open(WIREFILE, $WireFile) || die("Cannot open wire file\n");
while(<WIREFILE>) {
chop;
$_ = stripcomments $_;
@f = split /[ \t]+/, $_;
if ($#f < 1) { next; }
$wiretype{$f[0]} = $f[1];
}
close (WIREFILE);
}
##############################################################################
#
# Type Map Functions
#
##############################################################################
##############################################################################
#
# NAME
# _readTypeMap(typeMapFile)
#
# DESCRIPTION
# Create the type map by reading the specified typeMapFile
# invoking the _makeTypeMap() function.
#
# The type map uses a contextual wildcard character "*" for
# short-hand description of type maps. The expansion of "*"
# is as follows:
#
# Field "*" Wildcard Expansion
# ==================== ====================================
# unmapped-direction All directions (in, out, in/out)
# unmapped-transfer-type All transfer-types (array, reference,
# ... and value)
# mapped-direction Corresponding unmapped-direction
# mapped-transfer-type Corresponding unmapped-transfer-type
#
# TYPE MAP FILE BNF
# <type-map-file> ::= <type-map-line>*
# <type-map-line> :== [<type-map>] [<comment>]
# <type-map> :== <unmapped-type> "," <mapped-type>
# <meta-unmapped-type> :== <unmapped-declared-type> ","
# <meta-unmapped-direction> ","
# <meta-unmapped-transfer-type>
# <unmapped-declared-type> :== <type-name>
# <meta-unmapped-direction> :== <direction> | "*"
# <meta-unmapped-transfer-type> :== <transfer-type> | "*"
# <meta-mapped-type> :== <meta-mapped-declared-type> ","
# <meta-mapped-direction> ","
# <meta-mapped-transfer-type>
# <meta-mapped-declared-type> :== <type-name>
# <meta-mapped-direction> :== <direction> | "*"
# <meta-mapped-transfer-type> :== <transfer-type> | "*"
# <direction> :== "in" | "out" | "in/out"
# <transfer-type> :== "array" | "reference" | "value"
#
##############################################################################
sub _readTypeMap {
my ($typeMapFile, $d, $t) = @_;
if ($typeMapFile eq "") {
readError("libspec.pl", "no typeMapFile specified in _readTypeMap\n");
exit(1);
}
open(TYPEMAPFILE, $typeMapFile) || die("Cannot open typemapfile\n");
while (<TYPEMAPFILE>) {
chop;
$_ = stripcomments($_);
@f = split /[ \t]*,[ \t]*/, $_;
if ($f[1] eq "*") {
foreach $d (keys %validDirections) {
if ($f[2] eq "*") {
foreach $t (keys %validTransferTypes) {
_makeTypeMap($f[0], $d, $t, $f[3], $f[4], $f[5]);
}
} elsif (defined $validTransferTypes{$f[2]}) {
_makeTypeMap($f[0], $d, $f[2], $f[3], $f[4], $f[5]);
} else {
readError($typeMapFile, "unknown transfer type: " . $f[4]);
}
}
} elsif (defined $validDirections{$f[1]}) {
if ($f[2] eq "*") {
foreach $t (keys %validTransferTypes) {
_makeTypeMap($f[0], $f[1], $t, $f[3], $f[4], $f[5]);
}
} elsif (defined $validTransferTypes{$f[2]}) {
_makeTypeMap($f[0], $f[1], $f[2], $f[3], $f[4], $f[5]);
} else {
readError($typeMapFile, "unknown transfer type: " . $f[4]);
}
} else {
readError($typeMapFile, "unknown transfer type: " . $f[4]);
}
}
close TYPEMAPFILE;
}
sub _makeTypeMap {
my ($type, $direction, $transfer, $maptype, $mapdir, $maptrans) = @_;
$typeMap{$type, $direction, $transfer} = 1;
if ($maptype eq "*") {
$typeMapDeclaredType{$type, $direction, $transfer} = $type;
} else {
$typeMapDeclaredType{$type, $direction, $transfer} = $maptype;
}
if ($mapdir eq "*") {
$typeMapDirection{$type, $direction, $transfer} = $direction;
} elsif (defined $validDirections{$mapdir}) {
$typeMapDirection{$type, $direction, $transfer} = $mapdir;
} else {
error("unknown direction: " . $mapdir);
}
if ($maptrans eq "*") {
$typeMapTransferType{$type, $direction, $transfer} = $transfer;
} elsif (defined $validTransferTypes{$maptrans}) {
$typeMapTransferType{$type, $direction, $transfer} = $maptrans;
} else {
error("unknown transfer type: " . $maptrans);
}
}
##############################################################################
#
# NAME
# _parseValidPropsDeclaration()
#
# SPEC FILE BNF
# <valid-props-declaration> ::= <prop-name> ":" <prop-values>
# <prop-values> ::= (<blank> <prop-value>)*
#
# SETS
# validPropList[propname] -- Set of valid props
# -- ... [] is a comma separated list of
# -- ... valid prop values
# validPropListValues[propname,value]
# -- Set of valid (propname,values)
#
# _parseErrorOccured -- Flag indicating error in parsing
#
##############################################################################
sub _parseValidPropsDeclaration {
my ($i);
$f[0] =~ s/://; # get rid of color from list name
for ($i = 1; $i <= $#f; $i++) {
$validPropList{$f[0]} = 1;
$validPropListValues{$f[0], $f[$i]} = 1;
}
}
##############################################################################
#
# NAME
# _parseFunctionPrototype()
#
# SPEC FILE BNF
# <function-prototype> :== <function-name> "(" <param-list> ")"
# <param-list> :== [<param-name> ["," <param-name>]* ]
#
# SETS
# functionName -- Name of function currently being processed
# paramCount -- The number of parameters for function
# paramName[i] -- The name of the i-th parameter
# paramList[name] -- Set of parameter names for function
# -- ... [] is the parameter index
#
#
##############################################################################
sub _parseFunctionPrototype {
my (@protoFields) = split /[(), \t]+/, $_;
my ($i);
$functionName = $protoFields[0];
$paramCount = 0;
%paramList = ();
for ($i = 1; $i <= $#protoFields; $i++) {
$paramCount++;
$paramName{$paramCount} = $protoFields[$i];
$paramList{$protoFields[$i]} = $paramCount;
}
}
##############################################################################
#
# NAME
# _parseProp()
#
# SPEC FILE BNF
# <prop-line> ::= <prop-indent> <prop-name> <meta-prop-value>*
# <meta-prop-value> :== <blank> ["!"] ("all" | <prop-value>)
#
# SETS
# propList[propname] -- Set of properties for this function
# -- ... [] is a comma separated list of
# -- ... prop values
# _parseErrorOccured -- Flag indicating error in parsing
#
##############################################################################
sub _parseProp {
my ($i);
if (defined $validPropList{$f[0]}) { # if it is a valid prop
$propList{$f[0]} = ""; # create it for this function
for ($i = 1; $i <= $#f; $i++) {
if (!_parseMetaPropValue($f[0], $f[$i])) {
specError("unknown prop " . $f[0] . " value: " . $f[$i]);
$parseErrorOccured = 1;
}
}
} else {
specError("unknown prop " . $f[0] . "\n");
$parseErrorOccured = 1;
}
}
##############################################################################
#
# NAME
# _parseReturnType()
#
# DESCRIPTION
# Parse the return type. A "void" type implies a procedure or
# subroutine. Return type is the <unmapped-declared-type>.
# The <unmapped-direction> is implied to be "out" and the
# <unmapped-transfer-type> is implied to be "value".
#
# SPEC FILE BNF
# <unmapped-return-type> :== <unmapped-declared-type>
#
# SETS
# returnUnmappedType -- Return type from spec file
# returnType -- Converted or mapped return type
# _parseErrorOccured -- Flag indicating error in parsing
#
##############################################################################
sub _parseReturnType {
$returnUnmappedType = $f[1];
if (!defined $typeMap{$returnUnmappedType, "out", "value"}) {
# if returnUnmappedType is not a valid type ...
specError("return type " . $returnUnmappedType .
" is not defined in " . $typeMapFile);
$parseErrorOccured = 1;
} else {
$returnType = $typeMapDeclaredType{$returnUnmappedType,"out","value"};
}
}
##############################################################################
#
# NAME
# _parseParamPropBody()
#
# SPEC FILE BNF
# <param-prop-body> :== <param-name> <blank> <unmapped-param-type>
# [<blank> <length-descriptor>]
# [<param-options-list>]
# <unmapped-param-type> :== <unmapped-declared-type> <blank>
# <unmapped-direction> <blank>
# <unmapped-transfer-type>
# <unmapped-declared-type> :== <type-name>
# <unmapped-direction> :== "in" | "out" | "in/out"
# <unmapped-transfer-type> :== "array" | "reference" | "value"
# <length-descriptor> :== "[" <index-expr> ["," <index-expr> ]* "]"
# <index-expr> :== <integer> | <param-name> |
# ["("] <index-expr> <operator> <index-expr> [")"]
# <operator> :== "+" | "-" | "*" | "/"
# <param-options-list> :== (<blank> <list-prop-value>)*
#
# SETS
# paramUnmappedDeclaredType[name]
# -- Parameter type from spec file
# paramUnmappedDirection[name]
# -- Parameter direction [in,out,in/out] from
# -- ... spec file
# paramUnmappedTransferType[name]
# -- Parameter transfer type
# -- ... [value, reference, array] from spec fil
# paramDeclaredType[name] -- Parameter type from spec file
# paramDirection[name] -- Parameter direction [in,out,in/out] from
# -- ... spec file
# paramTransferType[name] -- Parameter transfer type
# -- ... [value, reference, array] from spec fil
# paramDimensions[name] -- The number dimensions of the array/length
# -- ... 0 if no array/length descriptor
# paramSubscripts[name,i] -- The size/value of the i-th dimension
# paramOptions[name] -- Space separated list of parameter options
# paramOptions[name,option]
# -- Set of options for parameter
# _parseErrorOccured -- Flag indicating error in parsing
#
##############################################################################
sub _parseParamPropBody {
my ($name);
my ($tmpLengthDesc);
my (@tmpSubscripts);
my ($i);
my (@operand);
my ($operands);
my ($processedLengthDesc);
$name = $f[1];
if (!defined $paramList{$name}) {
specError("param " . $name . " not in function prototype for "
. $functionName);
$parseErrorOccured = 1;
}
if (!defined $typeMap{$f[2], $f[3], $f[4]}) { # is the type mapped?
specError($f[2] . " " . $f[3] . " " . $f[4] . " is not defined in "
. $typeMapFile);
$parseErrorOccured = 1;
}
$paramUnmappedDeclaredType{$name} = $f[2];
$paramDirection{$name} = $f[3];
$paramTransferType{$name} = $f[4];
$paramDeclaredType{$name} = $typeMapDeclaredType{$f[2], $f[3], $f[4]};
$paramDirection{$name} = $typeMapDirection{$f[2], $f[3], $f[4]};
$paramTransferType{$name} = $typeMapTransferType{$f[2], $f[3], $f[4]};
#
# if the parameter has a length/array descriptor
# break it up into the following variables:
#
$paramDimensions{$name} = 0;
if ($f[5] =~ /^\[.*\]$/) {
$tmpLengthDesc = $f[5];
$tmpLengthDesc =~ s/[\[\]]//g;
@tmpSubscripts = split /,/, $tmpLengthDesc;
$paramDimensions{$name} = @tmpSubscripts; # number of elements
for ($i=0; $i < $paramDimensions{$name}; $i++) {
if ($tmpSubscripts[$i] ne "") {
$paramSubscripts{$name, $i+1} = $tmpSubscripts[$i];
if ($tmpSubscripts[$i] =~ /MAX/) {
$paramSubscripts{$name, $i+1} = $paramSubscripts{$name, $i+1} . "," . $tmpSubscripts[$i+1];
$i++;
$paramDimensions{$name}--;
}
} else {
specError("subscript " . $i . " is unspecified");
$parseErrorOccured = 1;
}
}
#
# check operands in subscripts to make sure they are legal
#
$operands = $f[5];
@operand = split /[-+\\\/*(),\[\]]/, $operands;
foreach $i (1 .. $#operand) {
# not an arg or a number
if (!(defined $paramList{$operand[$i]}) && !isConstant($operand[$i])) {
if (($operand[$i] ne "MAX") && ($operand[$i] ne "COMPSIZE")) {
# allow MAX and COMPSIZE keywords
specError("subscript size operand " . $operand[$i]
. " is not a parameter");
$parseErrorOccured = 1;
}
}
}
$processedLengthDesc = 1;
} else {
$processedLengthDesc = 0;
}
#
# process any parameter options if there are any
#
if ((!$processedLengthDesc) && ($#f > 4)) {
$i = 5; # if no len descr, start at field 6
} elsif ($processedLengthDesc && ($#f > 5)) {
$i = 6; # if len descr, start at field 7
} else {
$i = $#f + 1; # no parameter options;
}
for (; $i <= $#f; $i++) {
if (defined $validPropListValues{"param", $f[$i]}) {
$paramOptions{$name, $f[$i]} = 1;
$paramOptions{$name} = $paramOptions{$name} . $f[$i] . " ";
} else {
specError("unknown prop param value: " . $f[$i]);
}
}
}
##############################################################################
#
# NAME
# _parseMetaPropValue(name, value)
#
# DESCRIPTION
# Add name and value to propList array if name is a valid property
# If value is equal to all, all of the values from validPropList[]
# are added to propListValues. If the value begins with an exclamation
# point (!), the name,value pair is deleted from the propListValues.
# This ! negation permits "all but 'value'" short-hand notation.
#
# SPEC FILE BNF
# <meta-prop-value> :== <blank> ["!"] ("all" | <prop-value>)
#
# SETS
# propList[propname] -- Set of properties for this function
# -- ... [] is a comma separated list of
# -- ... prop values
# propListValues[propname,value]
# -- Set of (propname,values) for this function
#
#
##############################################################################
sub _parseMetaPropValue {
my ($name, $value) = @_;
my ($i);
my ($nf);
my (@values);
my ($s);
if ($value =~ /^!/) { # if negation, remove from list
$value =~ s/^!//g; # remove negation mark
if ($value eq "all") {
@values = split /,/, $validPropList{$name};
$nf = @values;
for ($i = 2; $i <= $nf; $i++) {
delete $propListValues{$name, $values[i]};
$s = "," . $values[$i];
$propList{$name} =~ s/$s//g;
}
} elsif (defined $validPropListValues{$name, $value}) {
delete $propListValues{$name, $value};
$s = "," . $value;
$propList{$name} =~ s/$s//g;
} elsif (defined $validPropListValues{$name,"*"}) {
delete $propListValues{$name, $value};
$s = "," . $value;
$propList{$name} =~ s/$s//g;
} else {
return 0; # propagate error up one level
}
} else { # if not negation, add to list
if ($value eq "all") {
$propList{$name} = $propList{$name} . $validPropList{$name};
@values = split /,/, $validPropList{$name};
$nf = @values;
for ($i = 2; $i <= $nf; $i++) {
$propListValues{$name, $values[$i]} = 1;
}
} elsif (defined $validPropListValues{$name, $value}) {
$propListValues{$name, $value} = 1;
$propList{$name} = $propList{$name} . "," . $value;
} elsif (defined $validPropListValues{$name, "*"}) {
$propListValues{$name, $value} = 1;
$propList{$name} = $propList{$name} . "," . $value;
} else {
return 0; # propagate error up one level
}
}
return 1;
}
#
# check for parsing errors
#
sub _parsingErrors {
if ($parsedPrototype) {
if (!$parsedReturn) {
specError("return type never parsed for " . $functionName);
$parseErrorOccured = 1;
}
foreach $i (keys %unparsedRequiredProps) {
specError("required prop " . $i . " never parsed for "
. $functionName);
$parseErrorOccured = 1;
}
return $parseErrorOccured;
} else {
return 1;
}
}
#
# print an error for the spec file being read
#
sub specError {
readError($specFile, $specline, @_);
}
#
# START HERE
#
# get options
%optionvars = ();
$optionstatus = GetOptions(\%optionvars,
"typemap=s",
"spec=s",
"copyright=s",
@options
);
$typeMapFile = $optionvars{"typemap"};
$specFile = $optionvars{"spec"};
# Do user's initialization
initialize();
# first check if user initialized everything needed
if ($typeMapFile eq "") {
readError($libSpecProgram, "no typeMapFile specified\n");
}
if ($specFile eq "") {
readError($libSpecProgram, "no spec file specified\n");
}
_readTypeMap($typeMapFile);
_resetParseStates();
# now go and read the spec file.
##############################################################################
#
# SECTION
# Parser pattern-actions
#
# DESCRIPTION
# The following awk pattern-action statements match input lines from
# the spec file and call the appropriate parsing functions to parse the
# lines. If the parsing function is trivial, then it is in-line coded
#
# SPEC FILE BNF
# <spec-file> :== <declaration-line>* <function-description>*
# <declaration-line> :== <required-props-declaration> |
# <valid-props-declaration>
# <function-description> :== <function-prototype> <prop-lines>
# <end-of-function-description>
#
# <return-prop-line> ::= <prop-indent> <return-prop>
# <return-prop> ::= "return" <blank> <unmapped-return-type>
#
# <param-prop-line> ::= <prop-indent> <param-prop>
# <param-prop> ::= "param" <blank> <param-prop-body>
#
# <prop-line> ::= <prop-indent> <prop-name> <meta-prop-value>*
#
##############################################################################
open(SPEC, $specFile) || die("libspec.pl: cannot open spec file\n");
$specline = 0;
while(<SPEC>) {
$specline++;
chop;
##############################################################################
#
# Parse passthru declaration
#
# SPEC FILE BNF
# <passthru-declaration> ::= "passthru: " <anything>*
#
# If anything follows the colon, the first space or tab (only) is stripped.
# This allows e.g. properly indented C declarations.
#
##############################################################################
if (/^passthru:/) {
s/^passthru:[ \t]?//;
passthru($_);
next;
}
##############################################################################
#
# Parse newcategory declaration
#
# SPEC FILE BNF
# <newcategory-declaration> ::= "newcategory: " <category-name>
#
##############################################################################
if (/^newcategory:/) {
s/^newcategory:[ \t]*//;
newcategory($_);
next;
}
##############################################################################
#
# Parse endcategory declaration
#
# SPEC FILE BNF
# <endcategory-declaration> ::= "endcategory: "
#
##############################################################################
if (/^endcategory:/) {
endcategory();
next;
}
##############################################################################
#
# Parse comment lines and comments from spec file
#
# SPEC FILE BNF
# <comment-line> ::= <comment>
# <comment> ::= <blank> "#" <text-upto-newline>
#
##############################################################################
if (/^[ \t]*\#/) { next; }
s/[ \t]*\#.*$//; # trim comments
@f = split /[ \t]+/;
# special case parsing when beginning with tab
if (/^\t/) {
$line = $_;
$line =~ s/^\t//;
@f = split /[ \t]+/, $line;
}
##############################################################################
#
# Parse return prop
#
# SPEC FILE BNF
# <return-prop-line> ::= <prop-indent> <return-prop>
# <return-prop> ::= "return" <blank> <unmapped-return-type>
#
##############################################################################
if ($f[0] eq "return") {
_parseReturnType();
$parsedReturn = 1;
next;
}
##############################################################################
#
# Parse param prop
#
# SPEC FILE BNF
# <param-prop-line> ::= <prop-indent> <param-prop>
# <param-prop> ::= "param" <blank> <param-prop-body>
#
##############################################################################
if ($f[0] eq "param") {
_parseParamPropBody();
next;
}
##############################################################################
#
# Parse prop lines
#
# SPEC FILE BNF
# <prop-line> ::= <prop-indent> <prop-name> <meta-prop-value>*
#
##############################################################################
if (/^\t/) {
_parseProp();
delete $unparsedRequiredProps{$f[0]}; # check off required prop
next;
}
##############################################################################
#
# Parse function prototype
#
# SPEC FILE BNF
# <function-prototype> :== <function-name> "(" <param-list> ")"
#
##############################################################################
if (/^[^\t]*\(/) {
_parseFunctionPrototype();
$parsedPrototype = 1;
# setup list to determine which props haven't yet been parsed
foreach $i (keys %requiredProps) {
$unparsedRequiredProps{$i} = 1;
}
next;
}
##############################################################################
#
# Parse end of function description
#
# SPEC FILE BNF
# <end-of-function-description> ::= ( <empty-line> | <end-of-file> )
#
##############################################################################
if (/^$/) {
if (!_parsingErrors()) {
main(); # user's main routine
}
_resetParseStates();
%propList = ();
%propListValues = ();
%paramName = ();
%paramList = ();
%paramUnmappedDeclaredType = ();
%paramUnmappedDirection = ();
%paramUnmappedTransferType = ();
%paramDeclaredType = ();
%paramDirection = ();
%paramTransferType = ();
%paramDimenstions = ();
%paramSubscripts = ();
%paramOptions = ();
next;
}
##############################################################################
#
# Parse required props declaration
#
# SPEC FILE BNF
# <required-props-declaration> ::= "required-props:"<required-prop-list>
# <required-prop-list> ::= (<blank> <prop-name>)*
#
# SETS
# requiredProps[propName] -- Set of required props
#
##############################################################################
if (/^required-props:/) {
for ($i=1; $i <= $#f; $i++) {
$requiredProps{$f[$i]} = 1;
}
next;
}
##############################################################################
#
# Parse valid props declarations
#
# SPEC FILE BNF
# <valid-props-declaration> ::= <prop-name> ":" <prop-values>
#
##############################################################################
if (/^[^\t]*:/) {
_parseValidPropsDeclaration();
next;
}
}
close SPEC;
if (!_parsingErrors()) {
main(); # user's main routine for final spec entry
}
finalize(); # user's finalize routine
# return a true value
1;