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