Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
#! perl
2
########################################################################
3
# Copyright ( C ) 2005 ERG Limited, All rights reserved
4
#
5
# Module name   : jats.sh
6
# Module type   : Perl Package
7
# Compiler(s)   : n/a
8
# Environment(s): jats
9
#
10
# Description   : This package contains functions to create a makefile entry
11
#                 The entry may consist of the following (optional) fields
12
#
13
#                 .PHONY <targets>
14
#                 <targets> : VARAIBLE = VALUE
15
#                 <targets> : <prerequisites>
16
#                       @echo "Run time comment"
17
#                       Recipe
18
#                       ( ShellRecipe )
19
#
20
#                 The order that information is added is not important
21
#                 Recipes and prerequisites may be mixed to simplify
22
#                 programming.
23
#
24
#......................................................................#
25
 
255 dpurdie 26
use 5.006_001;
227 dpurdie 27
use strict;
28
use warnings;
29
 
30
package MakeEntry;
31
use JatsError;
32
use ArrayHashUtils;
33
 
34
#
35
#   Global variables
36
#
37
my $llength = 80;                           # Target line length
38
 
39
 
40
#-------------------------------------------------------------------------------
41
# Function        : New
42
#
43
# Description     : Create a new empty entry
44
#
45
# Inputs          : FILEHANDLE          - eg: *MAKEFILE
46
#                   Name                - Primary target name
47
#                   Options             - Preload the fields
48
#                           --Target=name,name,name
49
#                           --Comment=text
50
#                           --Prereq=name,name,name
51
#                           --Recipe=text
52
#                           --Phony
53
#                           --Print
54
#
55
# Returns         : Ref to a an object that can be manipulated
56
#
57
sub New
58
{
59
    my ($handle, $name, @args ) = @_;
60
    my $self  = {};
61
    $self->{DEPENDANCY}     = [];
62
    $self->{NAME}           = [];
63
    $self->{RECIPE}         = [];
64
    $self->{SHELL}          = [];
65
    $self->{PRINTED}        = 0;
66
    $self->{COMMENT}        = [];
67
    $self->{DEFN}           = {};
68
    $self->{PHONY}          = 0;
69
    $self->{FH}             = $handle;
70
    $self->{RECIPE_PREFIX}  = '';
71
    $self->{RECIPE_COMMENT} = '';
72
 
73
    push @{$self->{NAME}}, split(/,/,$name) if ( $name );
74
 
75
    bless ($self, __PACKAGE__);
76
 
77
    #
78
    #   Process any argument
79
    #
80
    my $print = 0;
81
    foreach ( @args )
82
    {
83
        if ( m/^--Target=(.*)/ ) {
84
            $self->AddName(split(/,/,$1));
85
 
86
        } elsif ( m/^--Comment=(.*)/ ) {
87
            $self->AddComment($1);
88
 
89
        } elsif ( m/^--Prereq=(.*)/ ) {
90
            $self->AddDependancy(split(/,/,$1));
91
 
92
        } elsif ( m/^--Phony/ ) {
93
            $self->Phony();
94
 
95
        } elsif ( m/^--Recipe=(.*)/ ) {
96
            $self->AddRecipe($1);
97
 
98
        } elsif ( m/^--Print/ ) {
99
            $print = 1;
100
 
101
        } elsif ( m/^--/ ) {
102
            Error ("MakeEntry: Unknown option: $_");
103
 
104
        } else {
105
            $self->AddDependancy( $_ );
106
 
107
        }
108
    }
109
 
110
    $self->Print() if ( $print );
111
 
112
    return $self;
113
}
114
 
115
#-------------------------------------------------------------------------------
116
# Function        : AddName
117
#
118
# Description     : Add a name to the entry
119
#
120
# Inputs          : An array of names to add
121
#
122
# Returns         :
123
#
124
sub AddName
125
{
126
    my $self = shift;
127
    push @{$self->{NAME}}, @_
128
}
129
 
130
#-------------------------------------------------------------------------------
131
# Function        : Phony
132
#
133
# Description     : Flag the entry as a phony
134
#
135
# Inputs          :
136
#
137
# Returns         :
138
#
139
sub Phony
140
{
141
    my $self = shift;
142
    $self->{PHONY} = 1;
143
}
144
 
145
 
146
#-------------------------------------------------------------------------------
147
# Function        : AddComment
148
#
149
# Description     : Add a comment to the entry
150
#
151
# Inputs          : An array of names to add
152
#
153
# Returns         :
154
#
155
sub AddComment
156
{
157
    my $self = shift;
158
    push @{$self->{COMMENT}}, @_
159
}
160
 
161
#-------------------------------------------------------------------------------
162
# Function        : AddDependancy
163
#
164
# Description     : Add a dependancy to the entry
165
#
166
# Inputs          : An array of dependacies to add
167
#
168
# Returns         :
169
#
170
sub AddDependancy
171
{
172
    my $self = shift;
173
    UniquePush $self->{DEPENDANCY}, @_ ;
174
}
175
 
176
#-------------------------------------------------------------------------------
177
# Function        : AddDefn
178
#
179
# Description     : Add a definition to the entry
180
#
181
# Inputs          : A hash of definitions to add
182
#                   The Hash gets lost in the subcall. Its simply a list
183
#                   of NAME, VALUE pairs
184
#
185
# Returns         :
186
#
187
sub AddDefn
188
{
189
    my $self = shift;
190
    while ( @_ )
191
    {
192
        my $defn = shift;
193
        my $value = shift || '';
194
        $self->{DEFN}{$defn} = $value;
195
    }
196
}
197
 
198
#-------------------------------------------------------------------------------
199
# Function        : RecipePrefix
200
#
201
# Description     : Set the recipe prefix
202
#                   This will be added to ALL recipe entries
203
#
204
# Inputs          :
205
#
206
# Returns         :
207
#
208
sub RecipePrefix
209
{
210
    my $self = shift;
211
    my $prefix = shift || '';
212
    $self->{RECIPE_PREFIX} = $prefix;
213
}
214
 
215
#-------------------------------------------------------------------------------
216
# Function        : RecipeComment
217
#
218
# Description     : Add a runtime comment to the entry
219
#
220
# Inputs          : String to print at runtime
221
#
222
# Returns         :
223
#
224
sub RecipeComment
225
{
226
    my $self = shift;
227
    $self->{RECIPE_COMMENT} = join( ' ', @_);
228
}
229
 
230
 
231
 
232
#-------------------------------------------------------------------------------
233
# Function        : AddRecipe
234
#
235
# Description     : Add a line to the line-by-line recipe
236
#
237
# Inputs          : One or more recipe lines
238
#                   Each line of the recipe will be prefixed with the current
239
#                   recipe prefix.
240
#
241
#                   An array will be treated as a recipe with implicit line
242
#                   breakes for formatting purposes.
243
#
244
# Returns         :
245
#
246
sub AddRecipe
247
{
248
    my $self = shift;
249
    my $prefix = $self->{RECIPE_PREFIX};
250
    foreach ( @_ )
251
    {
252
        if (ref($_) eq "ARRAY")
253
        {
254
            $_->[0] = $prefix . $_->[0];
255
            push @{$self->{RECIPE}}, $_;
256
        }
257
        else
258
        {
259
            push @{$self->{RECIPE}}, $prefix . $_;
260
        }
261
    }
262
}
263
 
264
#-------------------------------------------------------------------------------
265
# Function        : AddShellRecipe
266
#
267
# Description     : Add recipe lines that will be processed within a 'shell'
268
#
269
# Inputs          : One or more recipe lines
270
#
271
#                   An array will be treated as a recipe with implicit line
272
#                   breakes for formatting purposes.
273
#
274
# Returns         :
275
#
276
sub AddShellRecipe
277
{
278
    my $self = shift;
279
    push @{$self->{SHELL}}, @_
280
}
281
 
282
 
283
#-------------------------------------------------------------------------------
284
# Function        : Print
285
#
286
# Description     : Print the entry
287
#
288
# Inputs          : None
289
#
290
# Returns         : Nothing
291
#
292
sub Print
293
{
294
    my $self = shift;
295
 
296
    #
297
    #   Set the default print stream to the desired stream
298
    #   This greatly simplifies the use of print
299
    #
300
    my $fh = $self->{FH};
301
        $fh = \*STDERR unless $fh;
302
    my $old_fh = select($fh);
303
#    my $old_fh = $fh;
304
 
305
    #
306
    #   A nice comment header
307
    #
308
    if ( @{$self->{COMMENT}} )
309
    {
310
        print( "#\n" );
311
        print map {"# $_\n"} @{$self->{COMMENT}};
312
        print( "#\n" );
313
    }
314
 
315
    #
316
    #   Print the targets
317
    #   Print PHONY information
318
    #   Print on multiple lines if multiple targets are very long
319
    #
320
    if ( $self->{PHONY} )
321
    {
322
        my $phony_string = ".PHONY: ";
323
        my $tstring = join $;, @{$self->{NAME}};
324
        my $join = length ($tstring) < $llength ? ' ' : "\n$phony_string";
325
        $tstring =~ s~$;~$join~g;
326
        print "$phony_string$tstring\n";
327
    }
328
 
329
    #
330
    #   Print any definitions
331
    #       target: DEFN = VALUE
332
    #
333
    if ( $self->{DEFN}  )
334
    {
335
        my $tstring = join $;, @{$self->{NAME}};
336
        my $join = length ($tstring) < $llength ? ' ' : " \\\n    ";
337
        $tstring =~ s~$;~$join~g;
338
        foreach  ( keys %{$self->{DEFN}}  )
339
        {
340
            my $value = $self->{DEFN} {$_};
341
            print( "$tstring: $_ = $value\n" );
342
        }
343
    }
344
 
345
    #
346
    #   Print the main target name
347
    #   Print on multiple lines if multiple targets are very long
348
    #
349
    my $tstring = join $;, @{$self->{NAME}};
350
    my $join = length ($tstring) < $llength ? ' ' : " \\\n";
351
    $tstring =~ s~$;~$join~g;
352
    my $nlength = length $tstring;
353
    print "$tstring:";
354
 
355
    #
356
    #   Print the prerequisites
357
    #   Print on multiple lines if long
358
    #
359
    $tstring = join $;, @{$self->{DEPENDANCY}};
360
    $join = $nlength + length ($tstring) < $llength ? ' ' : " \\\n\t";
361
    $tstring =~ s~$;~$join~g;
362
    print $join . $tstring;
363
 
364
 
365
    #
366
    #   Print the Recipe runtime comment
367
    #
368
    if ( $self->{RECIPE_COMMENT} )
369
    {
370
        print "\n\t\@echo \"$self->{RECIPE_COMMENT}\"";
371
    }
372
 
373
    #
374
    #   Print the recipe
375
    #
376
    print_list ( '', '', $self->{RECIPE}, '');
377
 
378
    #
379
    #   Print the recipe as a shell command
380
    #   Bracket the recipes with ( .. ) and place semi colons between lines
381
    #   Use the current recipe prefix
382
    #
383
    print_list ( $self->{RECIPE_PREFIX} . '(', ';\\', $self->{SHELL}, ')');
384
 
385
    print "\n\n";
386
 
387
    #
388
    #   Flag the entry as having been printed
389
    #   Used as a sanity test when the object is destroyed
390
    #
391
    $self->{PRINT} = 1;
392
 
393
    #
394
    #   Restore default output stream handle
395
    #
396
    select($old_fh);
397
}
398
 
399
#-------------------------------------------------------------------------------
400
# Function        : print_list
401
#
402
# Description     : Internal helper rouitine
403
#
404
# Inputs          : $prefix     - Optional prefix to wrap the list
405
#                                 If present will cause extra indentation
406
#                   $linesep    - Line seperator string
407
#                   $ref        - Ref to the list to display
408
#                                 Each element will be a line of text, or an
409
#                                 array of arguments which will be displayed on
410
#                                 new lines for pretty printing
411
#                   $suffix     - Optional suffix.
412
#
413
# Returns         :
414
#
415
sub print_list
416
{
417
    my ($prefix, $linesep ,$ref, $suffix) = @_;
418
    my @entry = @{$ref};
419
    my $leadin = "\t";
420
 
421
    if ( @entry  )
422
    {
423
        if ( $prefix )
424
        {
425
            print( "\n" . $leadin . $prefix . "\\" );
426
            $leadin .= "\t";
427
        }
428
 
429
        foreach ( @entry )
430
        {
431
            if (ref($_) eq "ARRAY")
432
            {
433
                my @array = @{$_};
434
                my $indent = '';
435
                my $tail = '';
436
                foreach ( @array )
437
                {
438
                    print( $tail . "\n" . $leadin . $indent . $_ );
439
                    $indent = "\t";
440
                    $tail = " \\";
441
                }
442
                print $linesep;
443
            }
444
            else
445
            {
446
                print( "\n" . $leadin . $_ . $linesep );
447
            }
448
        }
449
 
450
        if ( $suffix )
451
        {
452
            print( "\n" . $leadin . $suffix );
453
        }
454
    }
455
}
456
 
457
#-------------------------------------------------------------------------------
458
# Function        : DESTROY
459
#
460
# Description     : Sanity test
461
#
462
# Inputs          :
463
#
464
# Returns         :
465
#
466
sub DESTROY
467
{
468
    my $self = shift;
469
    unless ($self->{PRINT} )
470
    {
471
        $self->{PRINT} = 1;
472
        Error ("Destroying MakeEntry before printing.",
473
               "Name: @{$self->{NAME}}");
474
    }
475
}
476
 
477
1;
478
 
479