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