📄 creator.pm
字号:
package Creator;
# ************************************************************
# Description : Base class for workspace and project creators
# Author : Chad Elliott
# Create Date : 5/13/2002
# ************************************************************
# ************************************************************
# Pragmas
# ************************************************************
use strict;
use FileHandle;
use File::Basename;
use Parser;
use vars qw(@ISA);
@ISA = qw(Parser);
# ************************************************************
# Data Section
# ************************************************************
my(@statekeys) = ('global', 'include', 'template', 'ti',
'dynamic', 'static', 'relative', 'addtemp',
'addproj', 'progress', 'toplevel', 'baseprojs',
'feature_file', 'hierarchy', 'name_modifier',
'apply_project',
);
my(%all_written) = ();
# ************************************************************
# Subroutine Section
# ************************************************************
sub new {
my($class) = shift;
my($global) = shift;
my($inc) = shift;
my($template) = shift;
my($ti) = shift;
my($dynamic) = shift;
my($static) = shift;
my($relative) = shift;
my($addtemp) = shift;
my($addproj) = shift;
my($progress) = shift;
my($toplevel) = shift;
my($baseprojs) = shift;
my($feature) = shift;
my($hierarchy) = shift;
my($nmodifier) = shift;
my($applypj) = shift;
my($type) = shift;
my($self) = Parser::new($class, $inc);
$self->{'relative'} = $relative;
$self->{'template'} = $template;
$self->{'ti'} = $ti;
$self->{'global'} = $global;
$self->{'grammar_type'} = $type;
$self->{'type_check'} = $type . '_defined';
$self->{'global_read'} = 0;
$self->{'current_input'} = '';
$self->{'progress'} = $progress;
$self->{'addtemp'} = $addtemp;
$self->{'addproj'} = $addproj;
$self->{'toplevel'} = $toplevel;
$self->{'files_written'} = [];
$self->{'reading_global'} = 0;
$self->{'global_assign'} = {};
$self->{'assign'} = {};
$self->{'baseprojs'} = $baseprojs;
$self->{'dynamic'} = $dynamic;
$self->{'static'} = $static;
$self->{'feature_file'} = $feature;
$self->{'hierarchy'} = $hierarchy;
$self->{'name_modifier'} = $nmodifier;
$self->{'apply_project'} = $applypj;
$self->{'convert_slashes'} = $self->convert_slashes();
return $self;
}
sub collect_line {
my($self) = shift;
my($fh) = shift;
my($lref) = shift;
my($line) = shift;
my($status) = 1;
my($errorString) = '';
$$lref .= $self->strip_line($line);
if ($$lref =~ /\\$/) {
$$lref =~ s/\\$/ /;
}
else {
($status, $errorString) = $self->parse_line($fh, $$lref);
$$lref = '';
}
return $status, $errorString;
}
sub generate_default_input {
my($self) = shift;
my($status) = 0;
my($error) = '';
($status, $error) = $self->parse_line(undef, "$self->{'grammar_type'} {");
($status, $error) = $self->parse_line(undef, '}');
if (!$status) {
print STDERR "$error\n";
}
return $status;
}
sub parse_file {
my($self) = shift;
my($input) = shift;
my($oline) = $self->get_line_number();
## Read the input file and get the last line number
my($status, $errorString) = $self->read_file($input);
if (!$status) {
print STDERR $self->getcwd() .
"/$input: line " . $self->get_line_number() .
":\n$errorString\n";
}
elsif ($status && $self->{$self->{'type_check'}}) {
## If we are at the end of the file and the type we are looking at
## is still defined, then we have an error
print STDERR $self->getcwd() .
"/$input: line " . $self->get_line_number() .
":\nERROR: Did not " .
"find the end of the $self->{'grammar_type'}\n";
$status = 0;
}
$self->set_line_number($oline);
return $status;
}
sub generate {
my($self) = shift;
my($input) = shift;
my($status) = 1;
## Reset the files_written array between processing each file
$self->{'files_written'} = [];
## Allow subclasses to reset values before
## each call to generate().
$self->reset_values();
## Read the global configuration file
if (!$self->{'global_read'}) {
$status = $self->read_global_configuration();
$self->{'global_read'} = 1;
}
if ($status) {
$self->{'current_input'} = $input;
## An empty input file name says that we
## should generate a default input file and use that
if ($input eq '') {
$status = $self->generate_default_input();
}
else {
$status = $self->parse_file($input);
}
}
return $status;
}
sub parse_assignment {
my($self) = shift;
my($line) = shift;
my($values) = shift;
my($status) = 1;
if ($line =~ /^(\w+)\s*\+=\s*(.*)?/) {
my($name) = lc($1);
my($value) = $2;
push(@$values, 'assign_add', $name, $value);
}
elsif ($line =~ /^(\w+)\s*=\s*(.*)?/) {
my($name) = lc($1);
my($value) = $2;
push(@$values, 'assignment', $name, $value);
}
elsif ($line =~ /^(\w+)\s*\-=\s*(.*)?/) {
my($name) = lc($1);
my($value) = $2;
push(@$values, 'assign_sub', $name, $value);
}
else {
$status = 0;
}
return $status;
}
sub parse_known {
my($self) = shift;
my($line) = shift;
my($status) = 1;
my($errorString) = '';
my($type) = $self->{'grammar_type'};
my(@values) = ();
##
## Each regexp that looks for the '{' looks for it at the
## end of the line. It is purposely this way to decrease
## the amount of extra lines in each file. This
## allows for the most compact file as human readably
## possible.
##
if ($line eq '') {
}
elsif ($line =~ /^$type\s*(\([^\)]+\))?\s*(:.*)?\s*{$/) {
my($name) = $1;
my($parents) = $2;
if ($self->{$self->{'type_check'}}) {
$errorString = "ERROR: Did not find the end of the $type";
$status = 0;
}
else {
if (defined $parents) {
my(@parents) = ();
$parents =~ s/^://;
foreach my $parent (split(',', $parents)) {
$parent =~ s/^\s+//;
$parent =~ s/\s+$//;
if ($parent ne '') {
push(@parents, $parent);
}
}
if (!defined $parents[0]) {
## The : was used, but no parents followed. This
## is an error.
$errorString = 'ERROR: No parents listed';
$status = 0;
}
$parents = \@parents;
}
push(@values, $type, $name, $parents);
}
}
elsif ($line =~ /^}$/) {
if ($self->{$self->{'type_check'}}) {
push(@values, $type, $line);
}
else {
$errorString = "ERROR: Did not find the beginning of the $type";
$status = 0;
}
}
elsif ($line =~ /^(feature)\s*\(([^\)]+)\)\s*{$/) {
my($type) = $1;
my($name) = $2;
my(@names) = split(/\s*,\s*/, $name);
push(@values, $type, \@names);
}
elsif (!$self->{$self->{'type_check'}}) {
$errorString = "ERROR: No $type was defined";
$status = 0;
}
elsif ($self->parse_assignment($line, \@values)) {
## If this returns true, then we've found an assignment
}
elsif ($line =~ /^(\w+)\s*(\([^\)]+\))?\s*{$/) {
my($comp) = lc($1);
my($name) = $2;
if (defined $name) {
$name =~ s/^\(\s*//;
$name =~ s/\s*\)$//;
}
else {
$name = $self->get_default_component_name();
}
push(@values, 'component', $comp, $name);
}
else {
$errorString = "ERROR: Unrecognized line: $line";
$status = -1;
}
return $status, $errorString, @values;
}
sub parse_scope {
my($self) = shift;
my($fh) = shift;
my($name) = shift;
my($type) = shift;
my($validNames) = shift;
my($flags) = shift;
my($status) = 0;
my($errorString) = "ERROR: Unable to process $name";
if (!defined $flags) {
$flags = {};
}
while(<$fh>) {
my($line) = $self->strip_line($_);
if ($line eq '') {
}
elsif ($line =~ /^}/) {
$status = 1;
$errorString = '';
$self->handle_scoped_end($type, $flags);
last;
}
else {
my(@values) = ();
if ($self->parse_assignment($line, \@values)) {
if (defined $$validNames{$values[1]}) {
if ($values[0] eq 'assignment') {
$self->process_assignment($values[1], $values[2], $flags);
}
elsif ($values[0] eq 'assign_add') {
$self->process_assignment_add($values[1], $values[2], $flags);
}
elsif ($values[0] eq 'assign_sub') {
$self->process_assignment_sub($values[1], $values[2], $flags);
}
}
else {
$status = 0;
$errorString = "ERROR: Invalid assignment name: $values[1]";
last;
}
}
else {
($status, $errorString) = $self->handle_scoped_unknown($fh,
$type,
$flags,
$line);
if (!$status) {
last;
}
}
}
}
return $status, $errorString;
}
sub base_directory {
my($self) = shift;
return basename($self->getcwd());
}
sub generate_default_file_list {
my($self) = shift;
my($dir) = shift;
my($exclude) = shift;
my($dh) = new FileHandle();
my(@files) = ();
if (opendir($dh, $dir)) {
my($need_dir) = ($dir ne '.');
foreach my $file (grep(!/^\.\.?$/, readdir($dh))) {
my($skip) = 0;
## Prefix each file name with the directory only if it's not '.'
my($full) = ($need_dir ? "$dir/" : '') . $file;
if (defined $$exclude[0]) {
foreach my $exc (@$exclude) {
if ($full eq $exc) {
$skip = 1;
last;
}
}
}
if (!$skip) {
push(@files, $full);
}
}
if ($self->sort_files()) {
@files = sort { $self->file_sorter($a, $b) } @files;
}
closedir($dh);
}
return @files;
}
sub windows_crlf {
#my($self) = shift;
if ($^O eq 'MSWin32' || $^O eq 'cygwin') {
return "\n";
}
else {
return "\r\n";
}
}
sub transform_file_name {
my($self) = shift;
my($name) = shift;
$name =~ s/[\s\-]/_/g;
return $name;
}
sub file_written {
my($self) = shift;
my($file) = shift;
return (defined $all_written{$self->getcwd() . '/' . $file});
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -