1#! perl
2#---------------------------------------------------------------------------
3#  Project:  TwlSDK - xml2env
4#  File:     xml2env.pl
5#
6#  Copyright 2005-2008 Nintendo. All rights reserved.
7#
8#  These coded instructions, statements, and computer programs contain
9#  proprietary information of Nintendo of America Inc. and/or Nintendo
10#  Company Ltd., and are protected by Federal copyright law. They may
11#  not be disclosed to third parties or copied or duplicated in any form,
12#  in whole or in part, without the prior written consent of Nintendo.
13#
14#  $Date:: 2008-09-18#$
15#  $Rev: 8573 $
16#  $Author: okubata_ryoma $
17#---------------------------------------------------------------------------
18
19
20use strict;
21
22# Check availability of XML::Parser
23if (eval "require XML::Parser; return 1;" != 1){
24    printf "Use cygwin setup to insert the newest version of Perl and the expat library. Set up an environment that allows you to use XML::Parser. Then run again. \n";
25    exit;
26}
27
28require Getopt::Std;
29require XML::Parser;
30
31# Specify access to the handler routine as a parameter and initialize the parser
32my $parser = XML::Parser -> new(Handlers => {
33        Init =>    \&handle_doc_start,
34        Final =>   \&handle_doc_end,
35        Start =>   \&handle_elem_start,
36        End =>     \&handle_elem_end,
37        Char =>    \&handle_char_data,
38});
39
40my (%opts);
41my $c = Getopt::Std::getopts('o:h', \%opts);
42
43my ($src, $tmp, $line, $resource_name, $resource_count);
44
45# Output filename used when no options have been attached
46$tmp = $src . '.result.c';
47
48
49# h for help
50if(exists $opts{h} || scalar(@ARGV) < 1){
51    print "After the command enter one argument (the .xml file you want to search) \n";
52    print "Input example: perl xml2env.pl d:/test/main.xml \n";
53    print "In the above example, the file is in d:/test/ \n";
54    print "If in the argument you enter "-o\" followed by a file name, the script will output to the file. \n";
55    print "If you enter "-h\" in the argument, a simple help menu will be displayed. \n";
56    die "$!";
57}
58
59
60
61# Enter name of output file after the -o option
62if(exists $opts{o}){
63    $tmp = $opts{o};
64}
65
66# Enter the name of the file to be accessed without an option
67if(@ARGV){
68    $src = $ARGV[$resource_count];
69}
70
71open(FO, ">" . $tmp) or die ("cannot open $tmp to write.");
72
73my %default_type = (
74 "u8"         => "ENV_U8",
75 "s8"         => "ENV_S8",
76 "u16"        => "ENV_U16",
77 "s16"        => "ENV_S16",
78 "u32"        => "ENV_U32",
79 "s32"        => "ENV_S32",
80 "u64"        => "ENV_U64",
81 "s64"        => "ENV_S64",
82 "bool"       => "ENV_BOOL",
83 "string"     => "ENV_STRING",
84 "hexbinary"  => "ENV_BINARY"
85);
86
87$line = "/*---------------------------------------------------------------------------*/\n";
88$line .= "#include <nitro.h>\n";
89$line .= "//================================================================================\n";
90$line .= "\n";
91print   FO  $line;
92
93
94# Read data and parse
95my $file = $src;
96if($file){
97    $parser->parsefile($file);
98}
99else{
100    my $input = "";
101    while(<STDIN>){ $input .= $_; }
102    $parser->parse($input);
103}
104
105close(FO);
106exit;
107
108my ($record, $context, $resource_names, $datafile_name);
109
110# Handler
111
112# Output the top of the file simultaneously as processing starts
113sub handle_doc_start{
114    print "";
115}
116my ($class_name, $class_context);
117# Parser is called each time the launch of a new element is encountered
118sub handle_elem_start{
119    my($expat, $name, %atts) = @_;
120    $context = $name;
121
122    if($name =~ /resource/i){
123        $resource_names .= " $atts{'name'},";
124        print "ENVResource $atts{'name'}\[\] = {\n";
125        print   FO  "ENVResource $atts{'name'}\[\] = {\n";
126    }
127    elsif($name =~ /class/i){
128        $class_name = $atts{'name'};
129    }
130    else{
131        # In the loop, search for items coming under default_type and process
132        foreach my $i(keys %default_type){
133            if($name =~ /$i/i){
134                $class_context = "\"$class_name\.$atts{'name'}\",\t". "$default_type{$name}";
135                if($name =~ /hexbinary/i){
136                    if(exists $atts{'src'}){
137                        $datafile_name = $atts{'src'};
138                        # Initialize attribute values used when loading files
139                        $atts{'src'} = undef;
140                    }
141                }
142            }
143        }
144    }
145}
146
147# Store element-internal character data in the latest element buffer
148sub handle_char_data{
149    my($expat, $text) = @_;
150
151    $record->{$context} .= $text;
152
153}
154my ($line, $filedata, $char);
155# Call the parser each time the close of a new element is encountered
156sub handle_elem_end{
157    my($expat, $name) = @_;
158    if($name =~ /resource/i){
159        print "    ENV_RESOUCE_END\n};\n\n";
160        print   FO  "    ENV_RESOUCE_END\n};\n\n";
161    }
162    # When the element name is not 'class'
163    elsif($name ne 'class'){
164        if($name =~ /hexbinary/i){
165            # When the element name is 'hexbinary' and it is necessary to load a file
166            if($datafile_name){
167                open(FP, "<" . $datafile_name) or die ("cannot open $datafile_name to read.");
168                while(!eof(FP)) {
169                    $char = getc FP;
170                    # Convert characters to ASCII code
171                    $char = unpack("C", $char);
172                    # Convert ASCII code to hexadecimal
173                    $char = sprintf("%x", $char);
174                    $filedata .= '\x' . $char;
175                }
176                print "    $class_context( \"$filedata\" ),\n";
177                print   FO  "    $class_context( \"$filedata\" ),\n";
178                # Initialize file read flag
179                $datafile_name = undef;
180                $filedata = "";
181            }
182            else{
183                my @ascii;
184                my $hexdata;
185                # Convert characters to ASCII code
186                @ascii = unpack("C*", $record->{$context});
187                foreach my $i(@ascii){
188                    # Convert ASCII code to hexadecimal
189                    $hexdata .= '\x' . sprintf("%x", $i);
190                }
191                print "    $class_context( \"$hexdata\" ),\n";
192                print   FO  "    $class_context( \"$hexdata\" ),\n";
193                # Initialize text each time
194                $record->{$context} = "";
195            }
196        }
197        elsif($name =~ /string/i){
198            $record->{$context} =~ s/(["\\])/\\$1/g;
199            $record->{$context} =~ s/[\n]/\\n/g;
200            $record->{$context} =~ s/[\t]/\\t/g;
201            print "    $class_context( \"$record->{$context}\" ),\n";
202            print   FO  "    $class_context( \"$record->{$context}\" ),\n";
203            # Initialize text each time
204            $record->{$context} = "";
205        }
206        else{
207            # In the loop, search for items coming under default_type and process
208            foreach my $i(keys %default_type){
209                if($name =~ /$i/i){
210                    print "    $class_context( $record->{$context} ),\n";
211                    print   FO  "    $class_context( $record->{$context} ),\n";
212                    # Initialize text each time
213                    $record->{$context} = "";
214                }
215            }
216        }
217        # Initialize text
218        $class_context = "";
219        $context = "";
220    }
221}
222
223# Output end of file last
224sub handle_doc_end{
225    print "ENVResource* resourceArray\[\]={";
226    print   FO  "ENVResource* resourceArray\[\]={";
227    print "$resource_names";
228    print   FO  "$resource_names";
229    print " NULL };";
230    print   FO  " NULL };";
231}
232
233