1*9780544fSAndrew Rist#**************************************************************
2*9780544fSAndrew Rist#
3*9780544fSAndrew Rist#  Licensed to the Apache Software Foundation (ASF) under one
4*9780544fSAndrew Rist#  or more contributor license agreements.  See the NOTICE file
5*9780544fSAndrew Rist#  distributed with this work for additional information
6*9780544fSAndrew Rist#  regarding copyright ownership.  The ASF licenses this file
7*9780544fSAndrew Rist#  to you under the Apache License, Version 2.0 (the
8*9780544fSAndrew Rist#  "License"); you may not use this file except in compliance
9*9780544fSAndrew Rist#  with the License.  You may obtain a copy of the License at
10*9780544fSAndrew Rist#
11*9780544fSAndrew Rist#    http://www.apache.org/licenses/LICENSE-2.0
12*9780544fSAndrew Rist#
13*9780544fSAndrew Rist#  Unless required by applicable law or agreed to in writing,
14*9780544fSAndrew Rist#  software distributed under the License is distributed on an
15*9780544fSAndrew Rist#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9780544fSAndrew Rist#  KIND, either express or implied.  See the License for the
17*9780544fSAndrew Rist#  specific language governing permissions and limitations
18*9780544fSAndrew Rist#  under the License.
19*9780544fSAndrew Rist#
20*9780544fSAndrew Rist#**************************************************************
21*9780544fSAndrew Rist
22*9780544fSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir
25cdf0e10cSrcweirpackage par2script::work;
26cdf0e10cSrcweir
27cdf0e10cSrcweiruse par2script::existence;
28cdf0e10cSrcweiruse par2script::globals;
29cdf0e10cSrcweiruse par2script::remover;
30cdf0e10cSrcweir
31cdf0e10cSrcweir############################################
32cdf0e10cSrcweir# par2script working module
33cdf0e10cSrcweir############################################
34cdf0e10cSrcweir
35cdf0e10cSrcweirsub analyze_comma_separated_list
36cdf0e10cSrcweir{
37cdf0e10cSrcweir	my ($list, $listref) = @_;	# second parameter is optional
38cdf0e10cSrcweir
39cdf0e10cSrcweir	my @list = ();
40cdf0e10cSrcweir	my $locallistref;
41cdf0e10cSrcweir
42cdf0e10cSrcweir	if (!( $listref )) { $locallistref = \@list; }
43cdf0e10cSrcweir	else { $locallistref = $listref; }
44cdf0e10cSrcweir
45cdf0e10cSrcweir	par2script::remover::remove_leading_and_ending_comma(\$list);
46cdf0e10cSrcweir	par2script::remover::remove_leading_and_ending_whitespaces(\$list);
47cdf0e10cSrcweir
48cdf0e10cSrcweir	while ( $list =~ /^\s*(.*?)\s*\,\s*(.*)\s*$/ )
49cdf0e10cSrcweir	{
50cdf0e10cSrcweir		my $oneentry = $1;
51cdf0e10cSrcweir		$list = $2;
52cdf0e10cSrcweir		par2script::remover::remove_leading_and_ending_whitespaces(\$oneentry);
53cdf0e10cSrcweir		push(@{$locallistref}, $oneentry);
54cdf0e10cSrcweir	}
55cdf0e10cSrcweir
56cdf0e10cSrcweir	# the last entry
57cdf0e10cSrcweir
58cdf0e10cSrcweir	par2script::remover::remove_leading_and_ending_whitespaces(\$list);
59cdf0e10cSrcweir	push(@{$locallistref}, $list);
60cdf0e10cSrcweir
61cdf0e10cSrcweir	return $locallistref;
62cdf0e10cSrcweir}
63cdf0e10cSrcweir
64cdf0e10cSrcweir############################################
65cdf0e10cSrcweir# setting list of include pathes
66cdf0e10cSrcweir############################################
67cdf0e10cSrcweir
68cdf0e10cSrcweirsub setincludes
69cdf0e10cSrcweir{
70cdf0e10cSrcweir	my ($list) = @_;
71cdf0e10cSrcweir
72cdf0e10cSrcweir	# input is the comma separated list of include pathes
73cdf0e10cSrcweir
74cdf0e10cSrcweir	my $includes = analyze_comma_separated_list($list);
75cdf0e10cSrcweir
76cdf0e10cSrcweir	return $includes;
77cdf0e10cSrcweir}
78cdf0e10cSrcweir
79cdf0e10cSrcweir############################################
80cdf0e10cSrcweir# setting list of all par files
81cdf0e10cSrcweir############################################
82cdf0e10cSrcweir
83cdf0e10cSrcweirsub setparfiles
84cdf0e10cSrcweir{
85cdf0e10cSrcweir	my ($filename) = @_;
86cdf0e10cSrcweir
87cdf0e10cSrcweir	# input is the name of the list file
88cdf0e10cSrcweir	$filename =~ s/\@//;	# removing the leading \@
89cdf0e10cSrcweir
90cdf0e10cSrcweir	my $filecontent = par2script::files::read_file($filename);
91cdf0e10cSrcweir
92cdf0e10cSrcweir	my @parfiles = ();
93cdf0e10cSrcweir	my $parfilesref = \@parfiles;
94cdf0e10cSrcweir
95cdf0e10cSrcweir	foreach ( @{$filecontent} ) { $parfilesref = analyze_comma_separated_list($_, $parfilesref); }
96cdf0e10cSrcweir
97cdf0e10cSrcweir	return $parfilesref;
98cdf0e10cSrcweir}
99cdf0e10cSrcweir
100cdf0e10cSrcweir############################################
101cdf0e10cSrcweir# finding the correct include path
102cdf0e10cSrcweir# for the par files
103cdf0e10cSrcweir############################################
104cdf0e10cSrcweir
105cdf0e10cSrcweirsub make_complete_pathes_for_parfiles
106cdf0e10cSrcweir{
107cdf0e10cSrcweir	my ($parfiles, $includes) = @_;
108cdf0e10cSrcweir
109cdf0e10cSrcweir	my $oneparfile;
110cdf0e10cSrcweir
111cdf0e10cSrcweir	foreach $oneparfile ( @{$parfiles} )
112cdf0e10cSrcweir	{
113cdf0e10cSrcweir		my $foundparfile = 0;
114cdf0e10cSrcweir		my $includepath;
115cdf0e10cSrcweir
116cdf0e10cSrcweir		foreach $includepath ( @{$includes} )
117cdf0e10cSrcweir		{
118cdf0e10cSrcweir			my $parfile = "$includepath/$oneparfile";
119cdf0e10cSrcweir
120cdf0e10cSrcweir			if ( -f $parfile )
121cdf0e10cSrcweir			{
122cdf0e10cSrcweir				$foundparfile = 1;
123cdf0e10cSrcweir				$oneparfile = $parfile;
124cdf0e10cSrcweir				last;
125cdf0e10cSrcweir			}
126cdf0e10cSrcweir		}
127cdf0e10cSrcweir
128cdf0e10cSrcweir		if ( ! $foundparfile )
129cdf0e10cSrcweir		{
130cdf0e10cSrcweir			die "ERROR: Could not find parfile ${$parfiles}[$i] in includes pathes: $par2script::globals::includepathlist !\n";
131cdf0e10cSrcweir		}
132cdf0e10cSrcweir	}
133cdf0e10cSrcweir}
134cdf0e10cSrcweir
135cdf0e10cSrcweir######################################################
136cdf0e10cSrcweir# collecting one special item in the par files and
137cdf0e10cSrcweir# including it into the "definitions" hash
138cdf0e10cSrcweir######################################################
139cdf0e10cSrcweir
140cdf0e10cSrcweirsub collect_definitions
141cdf0e10cSrcweir{
142cdf0e10cSrcweir	my ($parfilecontent) = @_;
143cdf0e10cSrcweir
144cdf0e10cSrcweir	my $multidefinitionerror = 0;
145cdf0e10cSrcweir	my @multidefinitiongids = ();
146cdf0e10cSrcweir
147cdf0e10cSrcweir
148cdf0e10cSrcweir	foreach $oneitem ( @par2script::globals::allitems )
149cdf0e10cSrcweir	{
150cdf0e10cSrcweir		my $docollect = 0;
151cdf0e10cSrcweir		my $gid = "";
152cdf0e10cSrcweir		my %allitemhash = ();
153cdf0e10cSrcweir
154cdf0e10cSrcweir		for ( my $i = 0; $i <= $#{$parfilecontent}; $i++ )
155cdf0e10cSrcweir		{
156cdf0e10cSrcweir			my $line = ${$parfilecontent}[$i];
157cdf0e10cSrcweir
158cdf0e10cSrcweir			if ( $line =~ /^\s*$oneitem\s+(\w+)\s*$/ )
159cdf0e10cSrcweir			{
160cdf0e10cSrcweir				$gid = $1;
161cdf0e10cSrcweir				$docollect = 1;
162cdf0e10cSrcweir			}
163cdf0e10cSrcweir			else
164cdf0e10cSrcweir			{
165cdf0e10cSrcweir				$docollect = 0;
166cdf0e10cSrcweir			}
167cdf0e10cSrcweir
168cdf0e10cSrcweir			if ( $docollect )
169cdf0e10cSrcweir			{
170cdf0e10cSrcweir				my $currentline = $i;
171cdf0e10cSrcweir				my %oneitemhash;
172cdf0e10cSrcweir
173cdf0e10cSrcweir				while (! ( ${$parfilecontent}[$currentline] =~ /^\s*End\s*$/i ) )
174cdf0e10cSrcweir				{
175cdf0e10cSrcweir					if ( ${$parfilecontent}[$currentline] =~ /^\s*(.+?)\s*\=\s*(.+?)\s*\;\s*$/ )	# only oneliner!
176cdf0e10cSrcweir					{
177cdf0e10cSrcweir						$itemkey = $1;
178cdf0e10cSrcweir						$itemvalue = $2;
179cdf0e10cSrcweir
180cdf0e10cSrcweir						if ( $oneitem eq "Directory" ) { if ( $itemkey =~ "DosName" ) { $itemkey =~ s/DosName/HostName/; } }
181cdf0e10cSrcweir						if (( $oneitem eq "Directory" ) || ( $oneitem eq "File" ) || ( $oneitem eq "Unixlink" )) { if ( $itemvalue eq "PD_PROGDIR" ) { $itemvalue = "PREDEFINED_PROGDIR"; }}
182cdf0e10cSrcweir						if (( $itemkey eq "Styles" ) && ( $itemvalue =~ /^\s*(\w+)(\s*\;\s*)$/ )) { $itemvalue = "($1)$2"; }
183cdf0e10cSrcweir
184cdf0e10cSrcweir						$oneitemhash{$itemkey} = $itemvalue;
185cdf0e10cSrcweir					}
186cdf0e10cSrcweir
187cdf0e10cSrcweir					$currentline++;
188cdf0e10cSrcweir				}
189cdf0e10cSrcweir
190cdf0e10cSrcweir				# no hyphen allowed in gids -> cannot happen here because (\w+) is required for gids
191cdf0e10cSrcweir				if ( $gid =~ /-/ ) { par2script::exiter::exit_program("ERROR: No hyphen allowed in global id: $gid", "test_of_hyphen"); }
192cdf0e10cSrcweir
193cdf0e10cSrcweir				# test of uniqueness
194cdf0e10cSrcweir				if ( exists($allitemhash{$gid}) )
195cdf0e10cSrcweir				{
196cdf0e10cSrcweir					$multidefinitionerror = 1;
197cdf0e10cSrcweir					push(@multidefinitiongids, $gid);
198cdf0e10cSrcweir				}
199cdf0e10cSrcweir
200cdf0e10cSrcweir				$allitemhash{$gid} = \%oneitemhash;
201cdf0e10cSrcweir			}
202cdf0e10cSrcweir		}
203cdf0e10cSrcweir
204cdf0e10cSrcweir		$par2script::globals::definitions{$oneitem} = \%allitemhash;
205cdf0e10cSrcweir	}
206cdf0e10cSrcweir
207cdf0e10cSrcweir	if ( $multidefinitionerror ) {	par2script::exiter::multidefinitionerror(\@multidefinitiongids); }
208cdf0e10cSrcweir
209cdf0e10cSrcweir	# foreach $key (keys %par2script::globals::definitions)
210cdf0e10cSrcweir	# {
211cdf0e10cSrcweir	#	print "Key: $key \n";
212cdf0e10cSrcweir	#
213cdf0e10cSrcweir	#	foreach $key (keys %{$par2script::globals::definitions{$key}})
214cdf0e10cSrcweir	#	{
215cdf0e10cSrcweir	#		print "\t$key \n";
216cdf0e10cSrcweir	#	}
217cdf0e10cSrcweir	# }
218cdf0e10cSrcweir}
219cdf0e10cSrcweir
220cdf0e10cSrcweir######################################################
221cdf0e10cSrcweir# Filling content into the script
222cdf0e10cSrcweir######################################################
223cdf0e10cSrcweir
224cdf0e10cSrcweirsub put_oneitem_into_script
225cdf0e10cSrcweir{
226cdf0e10cSrcweir	my ( $script, $item, $itemhash, $itemkey ) = @_;
227cdf0e10cSrcweir
228cdf0e10cSrcweir	push(@{$script}, "$item $itemkey\n" );
229cdf0e10cSrcweir	my $content = "";
230cdf0e10cSrcweir	foreach $content (sort keys %{$itemhash->{$itemkey}}) { push(@{$script}, "\t$content = $itemhash->{$itemkey}->{$content};\n" ); }
231cdf0e10cSrcweir	push(@{$script}, "End\n" );
232cdf0e10cSrcweir	push(@{$script}, "\n" );
233cdf0e10cSrcweir}
234cdf0e10cSrcweir
235cdf0e10cSrcweir######################################################
236cdf0e10cSrcweir# Creating the script
237cdf0e10cSrcweir######################################################
238cdf0e10cSrcweir
239cdf0e10cSrcweirsub create_script
240cdf0e10cSrcweir{
241cdf0e10cSrcweir	my @script = ();
242cdf0e10cSrcweir	my $oneitem;
243cdf0e10cSrcweir
244cdf0e10cSrcweir	foreach $oneitem ( @par2script::globals::allitems )
245cdf0e10cSrcweir	{
246cdf0e10cSrcweir		if ( exists($par2script::globals::definitions{$oneitem}) )
247cdf0e10cSrcweir		{
248cdf0e10cSrcweir			if ( $oneitem eq "Shortcut" ) { next; } # "Shortcuts" after "Files"
249cdf0e10cSrcweir
250cdf0e10cSrcweir			if (( $oneitem eq "Module" ) || ( $oneitem eq "Directory" )) { write_sorted_items(\@script, $oneitem); }
251cdf0e10cSrcweir			else { write_unsorted_items(\@script, $oneitem); }
252cdf0e10cSrcweir		}
253cdf0e10cSrcweir	}
254cdf0e10cSrcweir
255cdf0e10cSrcweir	return \@script;
256cdf0e10cSrcweir}
257cdf0e10cSrcweir
258cdf0e10cSrcweir######################################################
259cdf0e10cSrcweir# Adding script content for the unsorted items
260cdf0e10cSrcweir######################################################
261cdf0e10cSrcweir
262cdf0e10cSrcweirsub write_unsorted_items
263cdf0e10cSrcweir{
264cdf0e10cSrcweir	my ( $script, $oneitem ) = @_;
265cdf0e10cSrcweir
266cdf0e10cSrcweir	my $itemhash = $par2script::globals::definitions{$oneitem};
267cdf0e10cSrcweir
268cdf0e10cSrcweir	my $itemkey = "";
269cdf0e10cSrcweir	foreach $itemkey (sort keys %{$itemhash})
270cdf0e10cSrcweir	{
271cdf0e10cSrcweir		put_oneitem_into_script($script, $oneitem, $itemhash, $itemkey);
272cdf0e10cSrcweir
273cdf0e10cSrcweir		# special handling for Shortcuts after Files
274cdf0e10cSrcweir		if (( $oneitem eq "File" ) && ( exists($par2script::globals::definitions{"Shortcut"}) ))
275cdf0e10cSrcweir		{
276cdf0e10cSrcweir			my $shortcutkey;
277cdf0e10cSrcweir			foreach $shortcutkey ( keys %{$par2script::globals::definitions{"Shortcut"}} )
278cdf0e10cSrcweir			{
279cdf0e10cSrcweir				if ( $par2script::globals::definitions{"Shortcut"}->{$shortcutkey}->{'FileID'} eq $itemkey )
280cdf0e10cSrcweir				{
281cdf0e10cSrcweir					put_oneitem_into_script($script, "Shortcut", $par2script::globals::definitions{"Shortcut"}, $shortcutkey);
282cdf0e10cSrcweir
283cdf0e10cSrcweir					# and Shortcut to Shortcut also
284cdf0e10cSrcweir					my $internshortcutkey;
285cdf0e10cSrcweir					foreach $internshortcutkey ( keys %{$par2script::globals::definitions{"Shortcut"}} )
286cdf0e10cSrcweir					{
287cdf0e10cSrcweir						if ( $par2script::globals::definitions{"Shortcut"}->{$internshortcutkey}->{'ShortcutID'} eq $shortcutkey )
288cdf0e10cSrcweir						{
289cdf0e10cSrcweir							put_oneitem_into_script($script, "Shortcut", $par2script::globals::definitions{"Shortcut"}, $internshortcutkey);
290cdf0e10cSrcweir						}
291cdf0e10cSrcweir					}
292cdf0e10cSrcweir				}
293cdf0e10cSrcweir			}
294cdf0e10cSrcweir		}
295cdf0e10cSrcweir	}
296cdf0e10cSrcweir}
297cdf0e10cSrcweir
298cdf0e10cSrcweir######################################################
299cdf0e10cSrcweir# Collecting all children of a specified parent
300cdf0e10cSrcweir######################################################
301cdf0e10cSrcweir
302cdf0e10cSrcweirsub collect_children
303cdf0e10cSrcweir{
304cdf0e10cSrcweir	my ( $itemhash, $parent, $order ) = @_;
305cdf0e10cSrcweir
306cdf0e10cSrcweir	my $item;
307cdf0e10cSrcweir	foreach $item ( keys %{$itemhash} )
308cdf0e10cSrcweir	{
309cdf0e10cSrcweir		if ( $itemhash->{$item}->{'ParentID'} eq $parent )
310cdf0e10cSrcweir		{
311cdf0e10cSrcweir			push(@{$order}, $item);
312cdf0e10cSrcweir			my $newparent = $item;
313cdf0e10cSrcweir			collect_children($itemhash, $newparent, $order);
314cdf0e10cSrcweir		}
315cdf0e10cSrcweir	}
316cdf0e10cSrcweir}
317cdf0e10cSrcweir
318cdf0e10cSrcweir######################################################
319cdf0e10cSrcweir# Adding script content for the sorted items
320cdf0e10cSrcweir######################################################
321cdf0e10cSrcweir
322cdf0e10cSrcweirsub write_sorted_items
323cdf0e10cSrcweir{
324cdf0e10cSrcweir	my ( $script, $oneitem ) = @_;
325cdf0e10cSrcweir
326cdf0e10cSrcweir	my $itemhash = $par2script::globals::definitions{$oneitem};
327cdf0e10cSrcweir
328cdf0e10cSrcweir	my @itemorder = ();
329cdf0e10cSrcweir	my @startparents = ();
330cdf0e10cSrcweir
331cdf0e10cSrcweir	if ( $oneitem eq "Module" ) { push(@startparents, ""); }
332cdf0e10cSrcweir	elsif ( $oneitem eq "Directory" ) { push(@startparents, "PREDEFINED_PROGDIR"); }
333cdf0e10cSrcweir	else { die "ERROR: No root parent defined for item type $oneitem !\n"; }
334cdf0e10cSrcweir
335cdf0e10cSrcweir	# supporting more than one toplevel item
336cdf0e10cSrcweir	my $parent;
337cdf0e10cSrcweir	foreach $parent ( @startparents ) { collect_children($itemhash, $parent, \@itemorder); }
338cdf0e10cSrcweir
339cdf0e10cSrcweir	my $itemkey;
340cdf0e10cSrcweir	foreach $itemkey ( @itemorder ) { put_oneitem_into_script($script, $oneitem, $itemhash, $itemkey); }
341cdf0e10cSrcweir}
342cdf0e10cSrcweir
343cdf0e10cSrcweir#######################################################################
344cdf0e10cSrcweir# Collecting all assigned gids of the type "item" from the modules
345cdf0e10cSrcweir# in the par files. Using a hash!
346cdf0e10cSrcweir#######################################################################
347cdf0e10cSrcweir
348cdf0e10cSrcweirsub collect_assigned_gids
349cdf0e10cSrcweir{
350cdf0e10cSrcweir	my $allmodules = $par2script::globals::definitions{'Module'};
351cdf0e10cSrcweir
352cdf0e10cSrcweir	my $item;
353cdf0e10cSrcweir	foreach $item ( @par2script::globals::items_assigned_at_modules )
354cdf0e10cSrcweir	{
355cdf0e10cSrcweir		if ( ! exists($par2script::globals::searchkeys{$item}) ) { par2script::exiter::exit_program("ERROR: Unknown type \"$item\" at modules.", "collect_assigned_gids"); }
356cdf0e10cSrcweir
357cdf0e10cSrcweir		my $searchkey = $par2script::globals::searchkeys{$item};
358cdf0e10cSrcweir
359cdf0e10cSrcweir		my %assignitems = ();
360cdf0e10cSrcweir		my $modulegid = "";
361cdf0e10cSrcweir
362cdf0e10cSrcweir		foreach $modulegid (keys %{$allmodules} )
363cdf0e10cSrcweir		{
364cdf0e10cSrcweir			# print "Module $modulegid\n";
365cdf0e10cSrcweir			# my $content = "";
366cdf0e10cSrcweir			# foreach $content (sort keys %{$allmodules->{$modulegid}}) { print "\t$content = $allmodules->{$modulegid}->{$content};\n"; }
367cdf0e10cSrcweir			# print "End\n";
368cdf0e10cSrcweir			# print "\n";
369cdf0e10cSrcweir
370cdf0e10cSrcweir			if ( exists($allmodules->{$modulegid}->{$searchkey}) )
371cdf0e10cSrcweir			{
372cdf0e10cSrcweir				my $list = $allmodules->{$modulegid}->{$searchkey};
373cdf0e10cSrcweir				if ( $list =~ /^\s*\((.*?)\)\s*(.*?)\s*$/ ) { $list = $1; }
374cdf0e10cSrcweir				else { par2script::exiter::exit_program("ERROR: Invalid module list: $list", "collect_assigned_gids"); }
375cdf0e10cSrcweir				my $allassigneditems = par2script::converter::convert_stringlist_into_array_2($list, ",");
376cdf0e10cSrcweir
377cdf0e10cSrcweir				my $gid;
378cdf0e10cSrcweir				foreach $gid ( @{$allassigneditems} )
379cdf0e10cSrcweir				{
380cdf0e10cSrcweir					if ( exists($assignitems{$gid}) ) { $assignitems{$gid} = $assignitems{$gid} + 1; }
381cdf0e10cSrcweir					else { $assignitems{$gid} = 1; }
382cdf0e10cSrcweir				}
383cdf0e10cSrcweir			}
384cdf0e10cSrcweir		}
385cdf0e10cSrcweir
386cdf0e10cSrcweir		$par2script::globals::assignedgids{$item} = \%assignitems;
387cdf0e10cSrcweir	}
388cdf0e10cSrcweir}
389cdf0e10cSrcweir
390cdf0e10cSrcweir##################################################
391cdf0e10cSrcweir# Collecting the content of all par files.
392cdf0e10cSrcweir# Then the files do not need to be opened twice.
393cdf0e10cSrcweir##################################################
394cdf0e10cSrcweir
395cdf0e10cSrcweirsub read_all_parfiles
396cdf0e10cSrcweir{
397cdf0e10cSrcweir	my ($parfiles) = @_;
398cdf0e10cSrcweir
399cdf0e10cSrcweir	my @parfilecontent = ();
400cdf0e10cSrcweir	my $parfilename;
401cdf0e10cSrcweir
402cdf0e10cSrcweir	foreach $parfilename ( @{$parfiles} )
403cdf0e10cSrcweir	{
404cdf0e10cSrcweir		my $parfile = par2script::files::read_file($parfilename);
405cdf0e10cSrcweir		foreach ( @{$parfile} ) { push(@parfilecontent, $_); }
406cdf0e10cSrcweir		push(@parfilecontent, "\n");
407cdf0e10cSrcweir	}
408cdf0e10cSrcweir
409cdf0e10cSrcweir	return \@parfilecontent;
410cdf0e10cSrcweir}
411cdf0e10cSrcweir
412cdf0e10cSrcweir1;
413