VT100debugport console no longer requires you to disable size detect in vt100.ini
#!perl# createsrc# # Copyright (c) 2009 - 2010 Accenture. All rights reserved.# This component and the accompanying materials are made available# under the terms of the "Eclipse Public License v1.0"# which accompanies this distribution, and is available# at the URL "http://www.eclipse.org/legal/epl-v10.html".# # Initial Contributors:# Accenture - Initial contribution#use strict;use Getopt::Long;use Cwd;use FindBin;# forward declssub homeDir();sub processCommandLine();sub Usage();sub make4CharId($);sub caseRename($$$);sub renameFileCopy($$);sub GetMacroValue($);sub PromptMacro($);sub CheckMacro($$);sub CheckUid($);sub CheckIdentifier($);sub listTemplates($);sub getTemplates();sub query($$);sub getConfigFileName();sub getConfig($);sub setConfig($$);sub setCopyright($);#globalsmy $template;my $newName;my $templateDir;my $templateName = "SkeletonTemplate";my $dest;my $help;my $verbose = 0;my %macroValue;my %macroDescription = ( 'UID' => 'a UID', 'COPYRIGHT' => 'a copyright notice' );my $homeDir;my $listTemplates;my $overwrite = 0;my $addToPerforce = 0;my $addToMercurial = 0;my $interactive = 0;processCommandLine();unless (defined $macroValue{'COPYRIGHT'}) { $macroValue{'COPYRIGHT'} = getConfig('copyright'); $macroValue{'COPYRIGHT'} = "Copyright (c) [[YEAR]] Accenture. All rights reserved." unless $macroValue{'COPYRIGHT'};}$homeDir = homeDir() unless defined ($homeDir);my $year = [localtime()]->[5]+1900;$macroValue{'COPYRIGHT'} =~ s|\[\[YEAR\]\]|$year|g;if ($interactive) { my $templates = getTemplates(); print "Available Templates:\n"; my $count = 1; my $options=""; foreach my $template (@$templates) { print "$count) $template->[0] - $template->[1]\n"; $options=$options . $count; $count++; } do { print "Which template do you want to use? "; my $in = <>; chomp $in; my $choice; $choice = eval "int($in)"; unless ($@) { if (($choice>0) && ($choice <= scalar(@$templates))) { $template = $templates->[$choice-1]->[0]; } } my $max = $count-1; print "Please enter a number between 1 and $max\n" unless defined $template; } until (defined $template); print "Using template $template\n" if $verbose; do { print "Name for the new code? "; $newName = <>; chomp $newName; unless (CheckIdentifier($newName)) { print "$newName is not a valid C++ identifier\n"; undef $newName; } } until ((defined $newName) && (length $newName)); my $cwd = cwd(); print "Directoy to create new code in? [$cwd] "; $dest = <>; chomp $dest; $dest = $cwd unless (length $dest);} else { $dest = cwd() unless $dest;}$templateDir = $homeDir."/createsrc-templates/$template";die "ERROR: Template $template not found at $templateDir\n" unless -d $templateDir;$dest =~ s|\\|/|g;$dest =~ s|/$||;print "Creating $newName at $dest from template $template at $templateDir\n" if ($verbose);# read [[MACRO]] descriptions from .txt filemy $infoFile;my $infoFileName = "$templateDir.txt";if ((-f $infoFileName) && (open $infoFile, $infoFileName)) { print "Reading $infoFileName\n" if ($verbose); <$infoFile>; # skip template description while (my $line = <$infoFile>) { chomp $line; $line =~ s|#.*||; # remove perl style comments if ($line =~ m|^\s*(\w[\w\d]*)\s*\:\s*(.*)$|) { my ($macro, $desc) = ($1, $2); print "Macro '$macro': '$desc'\n" if ($verbose>1); $macroDescription{$macro} = $desc; } elsif ($line =~ m|^\s*$|) { # blank line } else { die "Error: cannot parse line $. of $infoFileName\n"; } } close $infoFile;}unless (-d $dest) { mkdir($dest) or die "ERROR: Couldn't create directory $dest: $!\n"; print "Created directory $dest\n" if ($verbose>1);}my @dirStack;push @dirStack, "";while ($#dirStack>=0) { my $dir = pop(@dirStack); my $dirName = $dir; $dir = "/$dir" unless ($dir eq "") || ($dir =~ m|^/|); # create destination directory unless (-d "$dest$dir") { mkdir "$dest$dir" or die "ERROR: cannot create directory $dest$dir: $!\n"; print "Created directory $dest$dir\n" if ($verbose); } # read template directory contents opendir DIR, "$templateDir$dir"; my @dirContents = readdir(DIR); closedir(DIR); foreach my $f (@dirContents) { if (-f "$templateDir$dir/$f") { my $newFile = caseRename($f, $templateName, $newName); print "Renaming from $templateDir$dir/$f to $dest$dir/$newFile\n" if ($verbose); renameFileCopy("$templateDir$dir/$f", "$dest$dir/$newFile"); } elsif (-d "$templateDir$dir/$f") { unless ($f =~ m|^\.\.?$|) { print "Adding $dirName/$f to stack\n" if ($verbose); push @dirStack, "$dirName/$f"; } } else { print "WARNING: $templateDir$dir/$f is neither a file nor a directory"; } }}sub homeDir() { my $homeDir = $FindBin::Bin; print "homeDir=$homeDir\n" if ($verbose > 1); return $homeDir;}sub processCommandLine() { my $setCopyright = undef; Getopt::Long::Configure("bundling"); my @macroDefs; GetOptions('h' => \$help, 'v+' => \$verbose, 'd=s' => \$dest, 's=s' => \$homeDir, 't=s' => \$templateName, 'l' => \$listTemplates, 'o' => \$overwrite, 'p' => \$addToPerforce, 'm' => \$addToMercurial, 'i' => \$interactive, 'c=s' => \$setCopyright, 'D=s' => \@macroDefs); Usage() if ($help); listTemplates(1) if ($listTemplates); setCopyright($setCopyright) if (defined $setCopyright); unless ($interactive) { if ($#ARGV < 1) { print "Insufficient arguments; entering interactive mode\n"; $interactive = 1; } else { $template = shift(@ARGV); $newName = shift(@ARGV); die "$newName is not a valid C++ identifier\n" unless CheckIdentifier($newName); } } foreach my $d (@macroDefs) { if ($d =~ m|^(\w[\w\d]*)=(.*)$|) { my ($macro, $value) = ($1, $2); print "Got macro '$macro'='$value' from command line\n" if ($verbose>1); die "Error: '$value' is not a valid value for $macro\n" unless CheckMacro($macro, $value); $macroValue{$macro} = $value; } else { die "Error: Incorrect usage of -D: $d: expected a string of the format 'id=value'\n"; } } print "Warning: ignoring " . scalar(@ARGV) . " extra arguments\n" if scalar(@ARGV);}sub Usage() { require Pod::Text; my $parser = Pod::Text->new(); $parser->parse_from_file($0); exit;}sub make4CharId($) { my $longId = shift; while (length($longId)<2) { $longId = $longId . '_'; } return uc( substr($longId, 0, 2) . substr($longId, length($longId)-2, 2) );}sub caseRename($$$) { my $string = shift; my $oldName = shift; my $newName = shift; my $oldUpper = $oldName; $oldUpper =~ tr/a-z/A-Z/; my $oldLower = $oldName; $oldLower =~ tr/A-Z/a-z/; my $oldLowerFirst = "\l$oldName;\E"; my $uppercase = $newName; $uppercase =~ tr/a-z/A-Z/; my $lowercase = $newName; $lowercase =~ tr/A-Z/a-z/; my $lowerFirst = "\l$newName\E"; my $old4Char = make4CharId($oldName); my $new4Char = make4CharId($newName); $string =~ s/$oldName/$newName/g; $string =~ s/$oldUpper/$uppercase/g; $string =~ s/$oldLower/$lowercase/g; $string =~ s/$oldLowerFirst/$lowerFirst/g; $string =~ s/$old4Char/$new4Char/g; return $string;}sub renameFileCopy($$) { my $src = shift; my $dest = shift; open SOURCE, "<$src" or die "ERROR: can't open $src for reading: $!\n"; unless ($overwrite) { die "ERROR: $dest already exists. Use -o to overwrite. Aborting.\n" if (-f $dest); } open DEST, ">$dest" or die "ERROR: can't open $dest for writing: $!\n"; while (my $line = <SOURCE>) { while ($line =~ m|\[\[(\w[\w\d]*)\]\]|) { my $id = $1; my $value = GetMacroValue($id); $line =~ s|\[\[$id\]\]|$value|g; } print DEST caseRename($line, $templateName, $newName); } close (SOURCE); close (DEST); if ($addToPerforce) { print "p4 add $dest\n"; `p4 add $dest` ; } if ($addToMercurial) { print "hg add $dest\n"; `hg add $dest` ; }}sub GetMacroValue($) { my $macro = shift; if (!defined($macroValue{$macro})) { $macroValue{$macro} = PromptMacro($macro); } return $macroValue{$macro};}sub PromptMacro($) { my $macro = shift; my $description = $macroDescription{$macro}; $description = $macro unless defined $description; print "Enter $description for $newName: "; my $value; do { $value = <>; chomp $value; } while (!CheckMacro($macro, $value)); return $value;}sub CheckMacro($$) { my ($macro, $value) = @_; if ($macro eq 'UID') { return CheckUid($value); } return 1;}sub CheckUid($) { my $uid = shift; return 1 if ($uid =~ m|^0x[0-9a-f]{1,8}$|i); return 1 if ($uid =~ m|^[0-9]{1,10}$|); return 0;}sub CheckIdentifier($) { my $id = shift; return ($id =~ m|[A-Za-z_][A-Za-z_0-9]*|);}sub getTemplates() { $homeDir = homeDir() unless defined ($homeDir); opendir TEMPLATES, "$homeDir/createsrc-templates" or die "Can't read directory $homeDir/createsrc-templates: $!\n"; my @templateNames = grep((-d "$homeDir/createsrc-templates/$_")&&!(m|\.\.?|), readdir(TEMPLATES)); close TEMPLATES; die "No templates found at $homeDir/createsrc-templates\n" unless scalar(@templateNames); my @templates = (); foreach my $template (@templateNames) { my $desc; my $descFile = "$homeDir/createsrc-templates/$template.txt"; if ((-f $descFile)&&(open DESC, $descFile)) { $desc = <DESC>; chomp $desc; close DESC; } else { $desc = "<no description>"; } push @templates, [$template, $desc]; } @templates = sort {$a->[0] cmp $b->[0]} @templates; return \@templates;}sub listTemplates($) { my $exitWhenDone = shift; my $templates = getTemplates(); foreach my $template (@$templates) { print $template->[0] . " - " . $template->[1] . "\n"; } exit if $exitWhenDone;}sub getConfigFileName() { my $fn; if (defined $ENV{'USERPROFILE'}) { $fn = $ENV{'USERPROFILE'}; } else { $fn = homeDir(); } $fn =~ s|[/\\]$||; $fn .= "\\createsrc.cfg"; return $fn;}sub getConfig($) { my $findKey = shift; my $cfg = getConfigFileName(); my $foundValue = undef; open CFGFILE, "<$cfg" or return undef; print "Reading $cfg\n" if ($verbose); while (my $line = <CFGFILE>) { chomp $line; if ($line =~ m|^(.*?)\s*=\s*(.*)$|) { my ($key, $value) = ($1, $2); print "Read '$key'='$value'\n" if ($verbose>1); $foundValue = $value if ($key eq $findKey); } else { print "ignoring line '$line'\n" if ($verbose>1); } } return $foundValue; close CFGFILE; }sub setConfig($$) { my ($key, $value) = @_; my $cfg = getConfigFileName(); my @lines; if (open CFGFILE, "<$cfg") { print "Reading $cfg\n"; @lines = <CFGFILE>; close CFGFILE; } open CFGFILE, ">$cfg" or die "Cannot write to $cfg: $!\n"; print "Writing $cfg\n" if ($verbose); my $written = 0; foreach my $line (@lines) { if ($line =~ m|^(.*?)\s*=\s*(.*)$|) { my ($foundKey, $foundValue) = ($1, $2); print "Read '$foundKey'='$foundValue'\n" if ($verbose>1); if ($key eq $foundKey) { $foundValue = $value; $written = 1; print "Updated key $foundKey to '$foundValue'\n" if ($verbose>1); } print CFGFILE "$foundKey=$foundValue\n"; } else { print "ignoring line '$line'\n" if ($verbose>1); print CFGFILE $line; } } unless ($written) { print "Adding $key=$value\n"; print CFGFILE "$key=$value\n"; } close CFGFILE;}sub setCopyright($) { my $copyright = shift; print "Setting copyright notice to '$copyright'\n" if ($verbose); setConfig('copyright', $copyright); exit(1);}__END__=head1 NAMEcreatesrc - creates new code from templates=head1 SYNOPSIS createsrc [options] [TemplateName NewName]options:=over=item -iUse L<Interactive mode>. This will be the default if C<TemplateName> and C<NewName> are not given.=item -d <directory>Put the new code in the specified directory. Defaults to current directory.=item -DMACRO=valueSpecfies a value for a macro. See "Macros" section below.=item -c "Copyright Notice"Sets the default copyright to use when none other is specified. See L<Copyright Notices> below.=item -oOverwrites any existing files when creating the new code.=item -pAdd the new files to perforce as they are created.=item -mAdd the new files to mercurial as they are created.=item -s <directory>Specifies the home directory of the script, where the templates are located. Defaults to the directory where the script is located.=item -t <TemplateText>Specified the text to be replaced in the template. Defaults to C<SkeletonTemplate>. It's not usually necessary to change this.=item -lList available templates, then exits.=item -hShows this help.=item -vVerbose mode (-vv very verbose).=back=head1 DESCRIPTIONThis script creates new projects or code snippets from templates. For example, assuming you have a template C<UiqBasic> that consists of a basic UIQ application, you could create a HelloWorld application as follows: createsrc UiqBasic HelloWorldWhen creating the new code, it performs the following steps:=over=item 1.Copies and renames the files as appropriate.=item 2.Replaces text within the files as appropriate.=item 3.Substitutes macros enclosed in double square brackets, C<[[MACRO]]>.=backWhen renaming files or substituting text withing the files, case is preseved as follows:=over=item 1.C<MixedCaseText> is preserved - i.e. C<TemplateText> becomes C<NewText>.=item 2.C<lowercasetext> is preserved - i.e. C<templatetext> becomes C<newtext>.=item 3.C<UPPERCASETEXT> is preserved - i.e. C<TEMPLATETEXT> becomes C<NEWTEXT>.=item 4.C<lowerCaseFirst> is preserved - i.e. C<templateText> becomes C<newText>.=backThis should cover all forms of capitalisation used within normal Symbian code.In addition, the capitalised first and last two letters of C<TemplateText> is replaced with the same letters of C<NewText> - i.e. C<TEXT> becomes C<NEXT>. This is to support the C<NAME> value in an applications resource file, which must always have 4 letters.If the new text has less than 4 characters, it will be padded with underscores. For example, an application called C<A> will be given a C<NAME> of C<A_A_>; C<Ap> becomes C<APAP>; C<HelloWorld> becomes C<HELD> and so on.=head2 Interactive modeIf the C<-i> option is given, of if no C<TemplateName> and C<TemplateText> are given, interactive mode will be used: D:\work\new>createsrc Insufficient arguments; entering interactive mode Available Templates: 1) UiqBasic - Basic UIQ application 2) UiqImaging - Basic UIQ application with one large control, suitable for displaying an image, a video, etc. 3) UiqList - Basic UIQ application with a list in the view. 4) server - Symbian 9 transient server Which template do you want to use? 1 Name for the new code? HelloWorld Directoy to create new code in? [D:/work/new] Enter a UID for HelloWorld: 0x10002000When prompted for the directory to create the code in, simply hit enter to use the suggestion in square brackets. Or you can enter a relative or absolute path name to use instead.=head2 MacrosMacros allow extra custom strings to be inserted into the generate code. Macro values can be specified on the command line using the C<-D> option; if no value is specified then it will be prompted for at runtime.There are two macros that are used by all (or most) templates:=over=item C<COPYRIGHT>Defines a copyright notice for the code, usually inserted in a comment at the top of each source file. See L<Copyright Notices> below.=item C<UID>Specifies a UID for the new code. This will be verified as a valid integer.=backSome templates may define other, custom macros. To define a macro value on the command line, use -D syntax in a similar way the a C preprocessor: createsrc -DUID=0x01234567=head2 Copyright NoticesCopyright notices are automatically inserted into the source files, including the current year. When using the C<-DCOPYRIGHT=...> and C<-c> options, the copyright text may include C<[[YEAR]]>, which will be replaced with the current year when the code was created.For example, createsrc -DCOPYRIGHT="Copyright (c) [[YEAR]] Joe Bloggs. All rights reserved"The default copyright notice is C<Copyright (c) [[YEAR]] Accenture. All rights reserved.>When the C<-c> option is used, the copyright notice is stored in C<%USERPROFILE%\createsrc.cfg> and so is persisted for future runs of C<createsrc>.=head2 TemplatesThe templates are located in F<\epoc32\tools\Templates\TemplateName>. Each template usually contains an entire buildable project, but this may vary depending upon the nature of the template. The text that is replaced in template filenames and files is C<SkeletonTemplate> by default, but this can be modified with the C<-t TemplateText> option (although it is not recommended).In the template, macros are enclosed in double square brackets, for example C<[[UID]]>. Templates should make use of the standard C<[[UID]]> and C<[[COPYRIGHT]]> macros and can use others if necessary.If a F<TemplateName.txt> file is found in F<\epoc32\tools\Templates>, the first line of this file will be used as the description of the template when the C<-l> flag is given. The remainder of the file is expected to contain lines of the format: MACRO: descriptiongiving descriptions for any custom macros used in the project. The descriptions will be used instead of the macro name when prmopting the user for a value at runtime.=head1 COPYRIGHTCopyright (c) 2008-2010 Accenture. All rights reserved.=cut