Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
107 bj 1
package Options;
2
 
3
# ************************************************************
4
# Description   : Process mpc command line options
5
# Author        : Chad Elliott
6
# Create Date   : 3/20/2003
7
# ************************************************************
8
 
9
# ************************************************************
10
# Pragmas
11
# ************************************************************
12
 
13
use strict;
14
 
15
use DirectoryManager;
16
 
17
# ************************************************************
18
# Data Section
19
# ************************************************************
20
 
21
my(%languages) = ('cplusplus' => 1,
22
                  'csharp'    => 1,
23
                  'java'      => 1,
24
                  'vb'        => 1,
25
                 );
26
 
27
# ************************************************************
28
# Subroutine Section
29
# ************************************************************
30
 
31
sub printUsage {
32
  my($self)    = shift;
33
  my($msg)     = shift;
34
  my($base)    = shift;
35
  my($version) = shift;
36
  my($default) = shift;
37
  my(@types)   = @_;
38
 
39
  if (defined $msg) {
40
    print STDERR "ERROR: $msg\n";
41
  }
42
  my($spaces) = (' ' x (length($base) + 8));
43
  print STDERR "$base v$version\n" .
44
               "Usage: $base [-global <file>] [-include <directory>] [-recurse]\n" .
45
               $spaces . "[-ti <dll | lib | dll_exe | lib_exe>:<file>] [-hierarchy]\n" .
46
               $spaces . "[-template <file>] [-relative NAME=VAR] [-base <project>]\n" .
47
               $spaces . "[-noreldefs] [-notoplevel] [-static] [-genins] [-use_env]\n" .
48
               $spaces . "[-value_template <NAME+=VAL | NAME=VAL | NAME-=VAL>]\n" .
49
               $spaces . "[-value_project <NAME+=VAL | NAME=VAL | NAME-=VAL>]\n" .
50
               $spaces . "[-make_coexistence] [-feature_file <file name>]\n" .
51
               $spaces . "[-expand_vars] [-features <feature definitions>]\n" .
52
               $spaces . "[-exclude <directories>] [-name_modifier <pattern>]\n" .
53
               $spaces . "[-apply_project] [-version] [-into <directory>]\n" .
54
               $spaces . "[-language <";
55
 
56
  my(@keys) = sort keys %languages;
57
  for(my $i = 0; $i <= $#keys; $i++) {
58
    print STDERR $keys[$i];
59
    if ($i != $#keys) {
60
      print STDERR ' | ';
61
    }
62
    if ($i != $#keys && (($i + 1) % 4) == 0) {
63
      print STDERR "\n$spaces        ";
64
    }
65
  }
66
  print STDERR ">]\n",
67
               $spaces, "[-type <";
68
 
69
  @keys = sort @types;
70
  for(my $i = 0; $i <= $#keys; $i++) {
71
    print STDERR $keys[$i];
72
    if ($i != $#keys) {
73
      print STDERR ' | ';
74
    }
75
    if ($i != $#keys && (($i + 1) % 6) == 0) {
76
      print STDERR "\n$spaces        ";
77
    }
78
  }
79
  print STDERR ">]\n" .
80
               $spaces . "[files]\n\n";
81
 
82
  print STDERR
83
"       -base           Add <project> as a base project to each generated\n" .
84
"                       project file.  Do not provide a file extension, the\n" .
85
"                       .mpb extension will be tried first; if that fails the\n" .
86
"                       .mpc extension will be tried.\n" .
87
"       -exclude        Use this option to exclude directories when searching\n" .
88
"                       for input files.\n" .
89
"       -expand_vars    Perform direct expansion, instead of performing relative\n" .
90
"                       replacement with either -use_env or -relative options.\n" .
91
"       -feature_file   Specifies the feature file to read before processing.\n" .
92
"                       The default feature file is default.features under the\n" .
93
"                       config directory.\n" .
94
"       -features       Specifies the feature list to set before processing.\n" .
95
"       -genins         Generate .ins files for use with prj_install.pl.\n" .
96
"       -global         Specifies the global input file.  Values stored\n" .
97
"                       within this file are applied to all projects.\n" .
98
"       -hierarchy      Generate a workspace in a hierarchical fashion.\n" .
99
"       -include        Specifies a directory to search when looking for base\n" .
100
"                       projects, template input files and templates.  This\n" .
101
"                       option can be used multiple times to add directories.\n" .
102
"       -into           Place all output files in a mirrored directory\n" .
103
"                       structure starting at <directory>.\n" .
104
"       -language       Specify the language preference.  The default is\n".
105
"                       cplusplus.\n" .
106
"       -make_coexistence If multiple 'make' based project types are\n" .
107
"                       generated, they will be named such that they can coexist.\n" .
108
"       -name_modifier  Modify output names.  The pattern passed to this\n" .
109
"                       parameter will have the '*' portion replaced with the\n" .
110
"                       actual output name.  Ex. *_Static\n" .
111
"       -apply_project  When used in conjunction with -name_modifier, it applies\n" .
112
"                       the name modifier to the project name also.\n" .
113
"       -noreldefs      Do not try to generate default relative definitions.\n" .
114
"       -notoplevel     Do not generate the top level target file.  Files\n" .
115
"                       are still process, but no top level file is created.\n" .
116
"       -recurse        Recurse from the current directory and generate from\n" .
117
"                       all found input files.\n" .
118
"       -relative       Any \$() variable in an mpc file that is matched to NAME\n" .
119
"                       is replaced by VAR only if VAR can be made into a\n" .
120
"                       relative path based on the current working directory.\n" .
121
"       -static         Specifies that only static projects will be generated.\n" .
122
"                       By default, only dynamic projects are generated.\n" .
123
"       -ti             Specifies the template input file (with no extension)\n" .
124
"                       for the specific type (ex. -ti dll_exe:vc8exe).\n" .
125
"       -template       Specifies the template name (with no extension).\n" .
126
"       -type           Specifies the type of project file to generate.  This\n" .
127
"                       option can be used multiple times to generate multiple\n" .
128
"                       types.  If -type is not used, it defaults to '$default'.\n" .
129
"       -use_env        Use environment variables for all uses of \$() instead\n" .
130
"                       of the relative replacement values.\n" .
131
"       -value_project  This option allows modification of a project variable\n" .
132
"                       assignment .  Use += to add VAL to the NAME's value.\n" .
133
"                       Use -= to subtract and = to override the value.\n" .
134
"                       This can be used to introduce new name value pairs to\n" .
135
"                       a project.  However, it must be a valid project\n" .
136
"                       assignment.\n" .
137
"       -value_template This option allows modification of a template input\n" .
138
"                       name value pair.  Use += to add VAL to the NAME's\n" .
139
"                       value.  Use -= to subtract and = to override the value.\n" .
140
"       -version        Print the MPC version and exit.\n";
141
 
142
  exit(0);
143
}
144
 
145
 
146
sub optionError {
147
  #my($self) = shift;
148
  #my($str)  = shift;
149
}
150
 
151
 
152
sub completion_command {
153
  my($self)  = shift;
154
  my($name)  = shift;
155
  my($types) = shift;
156
  my($str)   = "complete $name " .
157
               "'c/-/(genins global include type template relative " .
158
               "ti static noreldefs notoplevel feature_file use_env " .
159
               "value_template value_project make_coexistence language " .
160
               "hierarchy exclude name_modifier apply_project version " .
161
               "expand_vars)/' " .
162
               "'c/dll:/f/' 'c/dll_exe:/f/' 'c/lib_exe:/f/' 'c/lib:/f/' " .
163
               "'n/-ti/(dll lib dll_exe lib_exe)/:' ";
164
 
165
  $str .= "'n/-language/(";
166
  my(@keys) = sort keys %languages;
167
  for(my $i = 0; $i <= $#keys; $i++) {
168
    $str .= $keys[$i];
169
    if ($i != $#keys) {
170
      $str .= " ";
171
    }
172
  }
173
  $str .= ")/' 'n/-type/(";
174
 
175
  @keys = sort keys %$types;
176
  for(my $i = 0; $i <= $#keys; $i++) {
177
    $str .= $keys[$i];
178
    if ($i != $#keys) {
179
      $str .= " ";
180
    }
181
  }
182
  $str .= ")/'";
183
  return $str;
184
}
185
 
186
 
187
sub options {
188
  my($self)       = shift;
189
  my($name)       = shift;
190
  my($types)      = shift;
191
  my($defaults)   = shift;
192
  my(@args)       = @_;
193
  my(@include)    = ();
194
  my(@input)      = ();
195
  my(@creators)   = ();
196
  my(@baseprojs)  = ();
197
  my(%ti)         = ();
198
  my(%relative)   = ();
199
  my(%addtemp)    = ();
200
  my(%addproj)    = ();
201
  my(@exclude)    = ();
202
  my($global)     = undef;
203
  my($template)   = undef;
204
  my($feature_f)  = undef;
205
  my(@features)   = ();
206
  my($nmodifier)  = undef;
207
  my($into)       = undef;
208
  my($hierarchy)  = 0;
209
  my($language)   = ($defaults ? 'cplusplus' : undef);
210
  my($dynamic)    = ($defaults ? 1 : undef);
211
  my($reldefs)    = ($defaults ? 1 : undef);
212
  my($toplevel)   = ($defaults ? 1 : undef);
213
  my($use_env)    = ($defaults ? 0 : undef);
214
  my($expandvars) = ($defaults ? 0 : undef);
215
  my($static)     = ($defaults ? 0 : undef);
216
  my($recurse)    = ($defaults ? 0 : undef);
217
  my($makeco)     = ($defaults ? 0 : undef);
218
  my($applypj)    = ($defaults ? 0 : undef);
219
  my($genins)     = ($defaults ? 0 : undef);
220
 
221
  ## Process the command line arguments
222
  for(my $i = 0; $i <= $#args; $i++) {
223
    my($arg) = $args[$i];
224
    $arg =~ s/^--/-/;
225
 
226
    if ($arg eq '-apply_project') {
227
      $applypj = 1;
228
    }
229
    elsif ($arg eq '-complete') {
230
      print $self->completion_command($name, $types) . "\n";
231
      return undef;
232
    }
233
    elsif ($arg eq '-base') {
234
      $i++;
235
      if (!defined $args[$i]) {
236
        $self->optionError('-base requires an argument');
237
      }
238
      else {
239
        push(@baseprojs, $args[$i]);
240
      }
241
    }
242
    elsif ($arg eq '-type') {
243
      $i++;
244
      if (!defined $args[$i]) {
245
        $self->optionError('-type requires an argument');
246
      }
247
      else {
248
        my($type) = lc($args[$i]);
249
        if (defined $types->{$type}) {
250
          my($call)  = $types->{$type};
251
          my($found) = 0;
252
          foreach my $creator (@creators) {
253
            if ($creator eq $call) {
254
              $found = 1;
255
              last;
256
            }
257
          }
258
          if (!$found) {
259
            push(@creators, $call);
260
          }
261
        }
262
        else {
263
          $self->optionError("Invalid type: $args[$i]");
264
        }
265
      }
266
    }
267
    elsif ($arg eq '-exclude') {
268
      $i++;
269
      if (defined $args[$i]) {
270
        @exclude = split(',', $args[$i]);
271
      }
272
      else {
273
        $self->optionError('-exclude requires a ' .
274
                           'comma separated list argument');
275
      }
276
    }
277
    elsif ($arg eq '-expand_vars') {
278
      $expandvars = 1;
279
    }
280
    elsif ($arg eq '-feature_file') {
281
      $i++;
282
      $feature_f = $args[$i];
283
      if (!defined $feature_f) {
284
        $self->optionError('-feature_file requires a file name argument');
285
      }
286
    }
287
    elsif ($arg eq '-features') {
288
      $i++;
289
      if (defined $args[$i]) {
290
        @features = split(',', $args[$i]);
291
      }
292
      else {
293
        $self->optionError('-features requires a comma separated list argument');
294
      }
295
    }
296
    elsif ($arg eq '-genins') {
297
      $genins = 1;
298
    }
299
    elsif ($arg eq '-global') {
300
      $i++;
301
      $global = $args[$i];
302
      if (!defined $global) {
303
        $self->optionError('-global requires a file name argument');
304
      }
305
    }
306
    elsif ($arg eq '-hierarchy') {
307
      $hierarchy = 1;
308
    }
309
    elsif ($arg eq '-include') {
310
      $i++;
311
      my($include) = $args[$i];
312
      if (!defined $include) {
313
        $self->optionError('-include requires a directory argument');
314
      }
315
      else {
316
        ## If the specified include path is relative, expand it based on
317
        ## the current working directory.
318
        if ($include !~ /^[\/\\]/ &&
319
            $include !~ /^[A-Za-z]:[\/\\]?/) {
320
          $include = DirectoryManager::getcwd() . '/' . $include;
321
        }
322
 
323
        push(@include, $include);
324
      }
325
    }
326
    elsif ($arg eq '-into') {
327
      $i++;
328
      $into = $args[$i];
329
      if (!defined $into) {
330
        $self->optionError('-into requires a directory argument');
331
      }
332
    }
333
    elsif ($arg eq '-language') {
334
      $i++;
335
      $language = $args[$i];
336
      if (!defined $language) {
337
        $self->optionError('-language requires a language argument');
338
      }
339
      elsif (!defined $languages{$language}) {
340
        $self->optionError("$language is not a valid language");
341
      }
342
    }
343
    elsif ($arg eq '-make_coexistence') {
344
      $makeco = 1;
345
    }
346
    elsif ($arg eq '-name_modifier') {
347
      $i++;
348
      my($nmod) = $args[$i];
349
      if (!defined $nmod) {
350
        $self->optionError('-name_modifier requires a modifier argument');
351
      }
352
      else {
353
        $nmodifier = $nmod;
354
      }
355
    }
356
    elsif ($arg eq '-noreldefs') {
357
      $reldefs = 0;
358
    }
359
    elsif ($arg eq '-notoplevel') {
360
      $toplevel = 0;
361
    }
362
    elsif ($arg eq '-recurse') {
363
      $recurse = 1;
364
    }
365
    elsif ($arg eq '-template') {
366
      $i++;
367
      $template = $args[$i];
368
      if (!defined $template) {
369
        $self->optionError('-template requires a file name argument');
370
      }
371
    }
372
    elsif ($arg eq '-relative') {
373
      $i++;
374
      my($rel) = $args[$i];
375
      if (!defined $rel) {
376
        $self->optionError('-relative requires a variable assignment argument');
377
      }
378
      else {
379
        if ($rel =~ /(\w+)\s*=\s*(.*)/) {
380
          my($name) = $1;
381
          my($val)  = $2;
382
          $val =~ s/^\s+//;
383
          $val =~ s/\s+$//;
384
 
385
          ## If the specified path is relative, expand it based on
386
          ## the current working directory.
387
          if ($val !~ /^[\/\\]/ &&
388
              $val !~ /^[A-Za-z]:[\/\\]?/) {
389
            $val = DirectoryManager::getcwd() . '/' . $val;
390
          }
391
 
392
          ## Clean up the path as much as possible
393
          $relative{$name} = File::Spec->canonpath($val);
394
          $relative{$name} =~ s/\\/\//g;
395
        }
396
        else {
397
          $self->optionError('Invalid argument to -relative');
398
        }
399
      }
400
    }
401
    elsif ($arg eq '-ti') {
402
      $i++;
403
      my($tmpi) = $args[$i];
404
      if (!defined $tmpi) {
405
        $self->optionError('-ti requires a template input argument');
406
      }
407
      else {
408
        if ($tmpi =~ /((dll|lib|dll_exe|lib_exe):)?(.*)/) {
409
          my($key)  = $2;
410
          my($name) = $3;
411
          if (defined $key) {
412
            $ti{$key} = $name;
413
          }
414
          else {
415
            foreach my $type ('dll', 'lib', 'dll_exe', 'lib_exe') {
416
              $ti{$type} = $name;
417
            }
418
          }
419
        }
420
        else {
421
          $self->optionError("Invalid -ti argument: $tmpi");
422
        }
423
      }
424
    }
425
    elsif ($arg eq '-use_env') {
426
      $use_env = 1;
427
    }
428
    elsif ($arg eq '-value_template') {
429
      $i++;
430
      my($value) = $args[$i];
431
      if (!defined $value) {
432
        $self->optionError('-value_template requires a variable assignment argument');
433
      }
434
      else {
435
        if ($value =~ /(\w+)\s*([\-+]?=)\s*(.*)/) {
436
          my($name) = lc($1);
437
          my($op)   = $2;
438
          my($val)  = $3;
439
          $val =~ s/^\s+//;
440
          $val =~ s/\s+$//;
441
          if ($op eq '+=') {
442
            $op = 1;
443
          }
444
          elsif ($op eq '-=') {
445
            $op = -1;
446
          }
447
          else {
448
            $op = 0;
449
          }
450
          if (!defined $addtemp{$name}) {
451
            $addtemp{$name} = [];
452
          }
453
          push(@{$addtemp{$name}}, [$op, $val]);
454
        }
455
        else {
456
          $self->optionError('Invalid argument to -value_template');
457
        }
458
      }
459
    }
460
    elsif ($arg eq '-value_project') {
461
      $i++;
462
      my($value) = $args[$i];
463
      if (!defined $value) {
464
        $self->optionError('-value_project requires a variable assignment argument');
465
      }
466
      else {
467
        if ($value =~ /(\w+)\s*([\-+]?=)\s*(.*)/) {
468
          my($name) = lc($1);
469
          my($op)   = $2;
470
          my($val)  = $3;
471
          $val =~ s/^\s+//;
472
          $val =~ s/\s+$//;
473
          if ($op eq '+=') {
474
            $op = 1;
475
          }
476
          elsif ($op eq '-=') {
477
            $op = -1;
478
          }
479
          else {
480
            $op = 0;
481
          }
482
          $addproj{$name} = [$op, $val];
483
        }
484
        else {
485
          $self->optionError('Invalid argument to -value_project');
486
        }
487
      }
488
    }
489
    elsif ($arg eq '-version') {
490
      print 'MPC v', Version::get(), "\n";
491
      return undef;
492
    }
493
    elsif ($arg eq '-static') {
494
      $static  = 1;
495
      $dynamic = 0;
496
    }
497
    elsif ($arg =~ /^-/) {
498
      $self->optionError("Unknown option: $arg");
499
    }
500
    else {
501
      push(@input, $arg);
502
    }
503
  }
504
 
505
  my(%options) = ('global'        => $global,
506
                  'feature_file'  => $feature_f,
507
                  'features'      => \@features,
508
                  'include'       => \@include,
509
                  'input'         => \@input,
510
                  'creators'      => \@creators,
511
                  'baseprojs'     => \@baseprojs,
512
                  'template'      => $template,
513
                  'ti'            => \%ti,
514
                  'dynamic'       => $dynamic,
515
                  'static'        => $static,
516
                  'relative'      => \%relative,
517
                  'reldefs'       => $reldefs,
518
                  'toplevel'      => $toplevel,
519
                  'recurse'       => $recurse,
520
                  'addtemp'       => \%addtemp,
521
                  'addproj'       => \%addproj,
522
                  'coexistence'   => $makeco,
523
                  'hierarchy'     => $hierarchy,
524
                  'exclude'       => \@exclude,
525
                  'name_modifier' => $nmodifier,
526
                  'apply_project' => $applypj,
527
                  'genins'        => $genins,
528
                  'into'          => $into,
529
                  'language'      => $language,
530
                  'use_env'       => $use_env,
531
                  'expand_vars'   => $expandvars,
532
                 );
533
 
534
  return \%options;
535
}
536
 
537
 
538
sub is_set {
539
  my($self)    = shift;
540
  my($key)     = shift;
541
  my($options) = shift;
542
 
543
  if (defined $options->{$key}) {
544
    if (UNIVERSAL::isa($options->{$key}, 'ARRAY')) {
545
      if (defined $options->{$key}->[0]) {
546
        return 'ARRAY';
547
      }
548
    }
549
    elsif (UNIVERSAL::isa($options->{$key}, 'HASH')) {
550
      my(@keys) = keys %{$options->{$key}};
551
      if (defined $keys[0]) {
552
        return 'HASH';
553
      }
554
    }
555
    else {
556
      return 'SCALAR';
557
    }
558
  }
559
 
560
  return undef;
561
}
562
 
563
1;