PageRenderTime 57ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/TemplateParser.pm

https://bitbucket.org/snaewe/mpc
Perl | 2354 lines | 1854 code | 321 blank | 179 comment | 274 complexity | 9cd18341dfca18a174fec189608e3fa5 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. package TemplateParser;
  2. # ************************************************************
  3. # Description : Parses the template and fills in missing values
  4. # Author : Chad Elliott
  5. # Create Date : 5/17/2002
  6. # $Id$
  7. # ************************************************************
  8. # ************************************************************
  9. # Pragmas
  10. # ************************************************************
  11. use strict;
  12. use File::Path;
  13. use Parser;
  14. use WinVersionTranslator;
  15. use vars qw(@ISA);
  16. @ISA = qw(Parser);
  17. # ************************************************************
  18. # Data Section
  19. # ************************************************************
  20. # Valid keywords for use in template files. Each has a handle_
  21. # method available, but some have other methods too.
  22. # Bit Meaning
  23. # 0 means there is a get_ method available (used by if and nested functions)
  24. # 1 means there is a perform_ method available (used by foreach and nested)
  25. # 2 means there is a doif_ method available (used by if)
  26. # 3 means that parameters to perform_ should not be evaluated
  27. # 4 means there is a post_ method available (called after the results of
  28. # calling perform_ for a nested function are written to the output)
  29. # 5 means that the get_ method performs the get_ and doif_ functionality
  30. #
  31. # Perl Function Parameter Type Return Type
  32. # get_ string string or array
  33. # perform_ array reference array
  34. # doif_ array reference boolean
  35. #
  36. my $get_type = 1 << 0;
  37. my $perform_type = 1 << 1;
  38. my $doif_type = 1 << 2;
  39. my $perform_no_eval_type = 1 << 3;
  40. my $post_type = 1 << 4;
  41. my $get_combined_type = 1 << 5;
  42. my %keywords = ('if' => 0,
  43. 'else' => 0,
  44. 'endif' => 0,
  45. 'noextension' => $get_type|$perform_type,
  46. 'dirname' => $get_type|$perform_type|$doif_type,
  47. 'basename' => $get_type|$perform_type|$doif_type,
  48. 'basenoextension' => 0,
  49. 'foreach' => 0,
  50. 'forfirst' => 0,
  51. 'fornotfirst' => 0,
  52. 'fornotlast' => 0,
  53. 'forlast' => 0,
  54. 'endfor' => 0,
  55. 'eval' => 0,
  56. 'comment' => 0,
  57. 'marker' => 0,
  58. 'uc' => $get_type|$perform_type,
  59. 'lc' => $get_type|$perform_type,
  60. 'ucw' => 0,
  61. 'normalize' => $get_type|$perform_type,
  62. 'flag_overrides' => $get_type,
  63. 'reverse' => $get_type|$perform_type,
  64. 'sort' => $get_type|$perform_type,
  65. 'uniq' => $get_type|$perform_type,
  66. 'multiple' => $get_type|$doif_type|$get_combined_type,
  67. 'starts_with' => $get_type|$doif_type|$get_combined_type,
  68. 'ends_with' => $get_type|$doif_type|$get_combined_type,
  69. 'contains' => $get_type|$doif_type|$get_combined_type,
  70. 'subst' => $get_type|$doif_type|$get_combined_type,
  71. 'remove_from' => $get_type|$perform_type|$doif_type|$perform_no_eval_type|$get_combined_type,
  72. 'compares' => $get_type|$doif_type|$get_combined_type,
  73. 'vars_equal' => $get_type|$perform_type,
  74. 'duplicate_index' => $get_type|$doif_type|$get_combined_type,
  75. 'transdir' => $get_type|$doif_type,
  76. 'has_extension' => $get_type|$doif_type|$get_combined_type,
  77. 'keyname_used' => 0,
  78. 'scope' => 0,
  79. 'full_path' => $get_type|$perform_type,
  80. 'extensions' => $perform_type|$perform_no_eval_type,
  81. 'create_aux_file' => $perform_type|$post_type,
  82. 'end_aux_file' => 0,
  83. 'translate_vars' => $get_type|$perform_type,
  84. 'convert_slashes' => $perform_type,
  85. 'new_guid' => 0,
  86. 'deref' => 0,
  87. 'set' => 0,
  88. );
  89. my %target_type_vars = ('type_is_static' => 1,
  90. 'need_staticflags' => 1,
  91. 'type_is_dynamic' => 1,
  92. 'type_is_binary' => 1,
  93. );
  94. my %arrow_op_ref = ('custom_type' => 'custom types',
  95. 'grouped_.*_file' => 'grouped files',
  96. 'feature' => 'features',
  97. );
  98. # optmized regex
  99. my $parse_line_re1 = qr/^[ ]*<%(\w+)(?:\((?:(?:\w+\s*,\s*)*[!]?\w+\(.+\)|[^\)]+)\))?%>$/;
  100. my $process_name_re1 = qr/([^%\(]+)(\(([^%]+)\))?%>/;
  101. # ************************************************************
  102. # Subroutine Section
  103. # ************************************************************
  104. sub new {
  105. my($class, $prjc) = @_;
  106. my $self = $class->SUPER::new();
  107. $self->{'prjc'} = $prjc;
  108. $self->{'ti'} = $prjc->get_template_input();
  109. $self->{'cslashes'} = $prjc->convert_slashes();
  110. $self->{'crlf'} = $prjc->crlf();
  111. $self->{'cmds'} = $prjc->get_command_subs();
  112. $self->{'vnames'} = $prjc->get_valid_names();
  113. $self->{'values'} = {};
  114. $self->{'defaults'} = {};
  115. $self->{'lines'} = [];
  116. $self->{'built'} = '';
  117. $self->{'sstack'} = [];
  118. $self->{'lstack'} = [];
  119. $self->{'if_skip'} = 0;
  120. $self->{'eval'} = 0;
  121. $self->{'eval_str'} = '';
  122. $self->{'dupfiles'} = {};
  123. $self->{'override_target_type'} = undef;
  124. $self->{'keyname_used'} = {};
  125. $self->{'scopes'} = {};
  126. $self->{'aux_file'} = undef;
  127. $self->{'foreach'} = {};
  128. $self->{'foreach'}->{'count'} = -1;
  129. $self->{'foreach'}->{'nested'} = 0;
  130. $self->{'foreach'}->{'name'} = [];
  131. $self->{'foreach'}->{'vars'} = [];
  132. $self->{'foreach'}->{'text'} = [];
  133. $self->{'foreach'}->{'scope'} = [];
  134. $self->{'foreach'}->{'scope_name'} = [];
  135. $self->{'foreach'}->{'temp_scope'} = [];
  136. $self->{'foreach'}->{'processing'} = 0;
  137. return $self;
  138. }
  139. sub tp_basename {
  140. my($self, $file) = @_;
  141. if ($self->{'cslashes'}) {
  142. $file =~ s/.*[\/\\]//;
  143. }
  144. else {
  145. $file =~ s/.*\///;
  146. }
  147. return $file;
  148. }
  149. sub validated_dirname {
  150. my($self, $file) = @_;
  151. my $index = rindex($file, ($self->{'cslashes'} ? '\\' : '/'));
  152. if ($index >= 0) {
  153. return $self->{'prjc'}->validated_directory(substr($file, 0, $index));
  154. }
  155. else {
  156. return '.';
  157. }
  158. }
  159. sub tp_dirname {
  160. my($self, $file) = @_;
  161. my $index = rindex($file, ($self->{'cslashes'} ? '\\' : '/'));
  162. if ($index >= 0) {
  163. return substr($file, 0, $index);
  164. }
  165. else {
  166. return '.';
  167. }
  168. }
  169. sub strip_line {
  170. #my $self = shift;
  171. #my $line = shift;
  172. ## Override strip_line() from Parser.
  173. ## We need to preserve leading space and
  174. ## there is no comment string in templates.
  175. ++$_[0]->{'line_number'};
  176. $_[1] =~ s/\s+$//;
  177. return $_[1];
  178. }
  179. ## Append the current value to the line that is being
  180. ## built. This line may be a foreach line or a general
  181. ## line without a foreach.
  182. sub append_current {
  183. my $value = $_[1];
  184. my $scope = $_[0]->{'scopes'};
  185. while(defined $$scope{'scope'}) {
  186. $scope = $$scope{'scope'};
  187. if (defined $$scope{'escape'}) {
  188. if ($$scope{'escape'}->[1] < 0 && $_[0]->{'foreach'}->{'count'} >= 0) {
  189. ## This scope was created outside of a foreach. If we are
  190. ## processing a foreach, we need to skip this at this point as it
  191. ## will be handled once the foreach has been completed and is
  192. ## appended to the main project body.
  193. last;
  194. }
  195. else {
  196. my $key = $$scope{'escape'}->[0];
  197. if ($key eq '\\') {
  198. $value =~ s/\\/\\\\/g;
  199. }
  200. else {
  201. $value =~ s/($key)/\\$1/g;
  202. }
  203. }
  204. }
  205. else {
  206. foreach my $key (keys %$scope) {
  207. $_[0]->warning("Unrecognized scope function: $key.");
  208. }
  209. }
  210. }
  211. my $foreach_count = $_[0]->{'foreach'}->{'count'};
  212. if ($_[0]->{'aux_file'}
  213. && $foreach_count == $_[0]->{'aux_file'}->{'foreach_baseline'}) {
  214. $_[0]->{'aux_file'}->{'text'} .= $value;
  215. }
  216. elsif ($foreach_count >= 0) {
  217. $_[0]->{'foreach'}->{'text'}->[$foreach_count] .= $value;
  218. }
  219. elsif ($_[0]->{'eval'}) {
  220. $_[0]->{'eval_str'} .= $value;
  221. }
  222. else {
  223. $_[0]->{'built'} .= $value;
  224. }
  225. }
  226. sub split_parameters {
  227. my($self, $str) = @_;
  228. my @params;
  229. while($str =~ /^(\w+\([^\)]+\))(.*)/ || $str =~ /^([^,]+)(.*)/) {
  230. push(@params, $1);
  231. $str = $2;
  232. $str =~ s/^\s*,\s*//;
  233. }
  234. ## Return the parameters (which includes whatever is left in the
  235. ## string). Just return it instead of pushing it onto @params.
  236. return $str eq '' ? @params : (@params, $str);
  237. }
  238. sub set_current_values {
  239. my($self, $name) = @_;
  240. my $set = 0;
  241. ## If any value within a foreach matches the name
  242. ## of a hash table within the template input we will
  243. ## set the values of that hash table in the current scope
  244. if (defined $self->{'ti'}) {
  245. my $counter = $self->{'foreach'}->{'count'};
  246. if ($counter >= 0) {
  247. ## Variable names are case-insensitive in MPC, however this can
  248. ## cause problems when dealing with template variable values that
  249. ## happen to match HASH names only by case-insensitivity. So, we
  250. ## now make HASH names match with case-sensitivity.
  251. my $value = $self->{'ti'}->get_value($name);
  252. if (defined $value && UNIVERSAL::isa($value, 'HASH') &&
  253. $self->{'ti'}->get_realname($name) eq $name) {
  254. $self->{'foreach'}->{'scope_name'}->[$counter] = $name;
  255. my %copy;
  256. foreach my $key (keys %$value) {
  257. $copy{$key} = $self->{'prjc'}->adjust_value(
  258. [$name . '::' . $key, $name], $$value{$key}, $self);
  259. }
  260. $self->{'foreach'}->{'temp_scope'}->[$counter] = \%copy;
  261. $set = 1;
  262. }
  263. else {
  264. ## Since we're not creating a temporary scope for this level, we
  265. ## need to empty out the scope that may have been held here from
  266. ## a previous foreach.
  267. $self->{'foreach'}->{'temp_scope'}->[$counter] = {};
  268. }
  269. }
  270. }
  271. return $set;
  272. }
  273. sub get_value {
  274. my($self, $name) = @_;
  275. my $value;
  276. my $counter = $self->{'foreach'}->{'count'};
  277. my $fromprj;
  278. my @scopes;
  279. my @snames;
  280. my $adjust = 1;
  281. ## $name should always be all lower-case
  282. $name = lc($name);
  283. ## First, check the temporary scope (set inside a foreach)
  284. if ($counter >= 0) {
  285. ## Create a list of possible scoped names
  286. @scopes = reverse @{$self->{'foreach'}->{'scope_name'}};
  287. @snames = map { defined $_ ? $_ . '::' . $name : $name } @scopes;
  288. push(@snames, $name);
  289. while(!defined $value && $counter >= 0) {
  290. $value = $self->{'foreach'}->{'temp_scope'}->[$counter]->{$name};
  291. --$counter;
  292. }
  293. $counter = $self->{'foreach'}->{'count'};
  294. if ($self->{'override_target_type'} &&
  295. defined $value && defined $target_type_vars{$name}) {
  296. $value = $self->{'values'}->{$name};
  297. }
  298. }
  299. else {
  300. @snames = ($name);
  301. }
  302. if (!defined $value) {
  303. if ($name =~ /^flag_overrides\((.*)\)$/) {
  304. $value = $self->get_flag_overrides($1);
  305. }
  306. if (!defined $value) {
  307. ## Next, check for a template value
  308. if (defined $self->{'ti'}) {
  309. $value = $self->{'ti'}->get_value($name);
  310. }
  311. if (!defined $value) {
  312. ## Calling adjust_value here allows us to pick up template
  313. ## overrides before getting values elsewhere.
  314. my $uvalue = $self->{'prjc'}->adjust_value(\@snames, [], $self);
  315. if (defined $$uvalue[0]) {
  316. $value = $uvalue;
  317. $adjust = 0;
  318. $fromprj = 1;
  319. }
  320. if (!defined $value) {
  321. ## Next, check the inner to outer foreach
  322. ## scopes for overriding values
  323. while(!defined $value && $counter >= 0) {
  324. $value = $self->{'foreach'}->{'scope'}->[$counter]->{$name};
  325. --$counter;
  326. }
  327. ## Then get the value from the project creator
  328. if (!defined $value) {
  329. $fromprj = 1;
  330. $value = $self->{'prjc'}->get_assignment($name);
  331. ## Then get it from our known values
  332. if (!defined $value) {
  333. $value = $self->{'values'}->{$name};
  334. if (!defined $value) {
  335. ## Call back onto the project creator to allow
  336. ## it to fill in the value before defaulting to undef.
  337. $value = $self->{'prjc'}->fill_value($name);
  338. if (!defined $value && $name =~ /^(.*)\->(\w+)/) {
  339. my $pre = $1;
  340. my $post = $2;
  341. my $base = $self->get_value($pre);
  342. if (defined $base) {
  343. $value = $self->{'prjc'}->get_special_value(
  344. $pre, $post, $base,
  345. ($self->{'prjc'}->requires_parameters($post) ?
  346. $self->prepare_parameters($pre) : undef));
  347. }
  348. }
  349. }
  350. }
  351. }
  352. }
  353. }
  354. }
  355. }
  356. ## Adjust the value even if we haven't obtained one from an outside
  357. ## source.
  358. if ($adjust && defined $value) {
  359. $value = $self->{'prjc'}->adjust_value(\@snames, $value, $self);
  360. }
  361. ## If the value did not come from the project creator, we
  362. ## check the variable name. If it is a project keyword we then
  363. ## check to see if we need to add the project value to the template
  364. ## variable value. If so, we make a copy of the value array and
  365. ## push the project value onto that (to avoid modifying the original).
  366. if (!$fromprj && defined $self->{'vnames'}->{$name} &&
  367. $self->{'prjc'}->add_to_template_input_value($name)) {
  368. my $pjval = $self->{'prjc'}->get_assignment($name);
  369. if (defined $pjval) {
  370. my @copy = @$value;
  371. if (!UNIVERSAL::isa($pjval, 'ARRAY')) {
  372. $pjval = $self->create_array($pjval);
  373. }
  374. push(@copy, @$pjval);
  375. $value = \@copy;
  376. }
  377. }
  378. return (defined $value ?
  379. $self->{'prjc'}->relative($value, undef, \@scopes) : undef);
  380. }
  381. sub get_value_with_default {
  382. my $self = shift;
  383. my $name = lc(shift);
  384. my $value = $self->get_value($name);
  385. if (!defined $value) {
  386. $value = $self->{'defaults'}->{$name};
  387. if (defined $value) {
  388. my $counter = $self->{'foreach'}->{'count'};
  389. my $sname;
  390. if ($counter >= 0) {
  391. ## Find the outer most scope for our variable name
  392. for(my $index = $counter; $index >= 0; --$index) {
  393. if (defined $self->{'foreach'}->{'scope_name'}->[$index]) {
  394. $sname = $self->{'foreach'}->{'scope_name'}->[$index] .
  395. '::' . $name;
  396. last;
  397. }
  398. }
  399. }
  400. $value = $self->{'prjc'}->relative(
  401. $self->{'prjc'}->adjust_value(
  402. [$sname, $name], $value, $self));
  403. ## If the user set the variable to empty, we will go ahead and use
  404. ## the default value (since we know we have one at this point).
  405. $value = $self->{'defaults'}->{$name} if (!defined $value);
  406. }
  407. else {
  408. #$self->warning("$name defaulting to empty string.");
  409. $value = '';
  410. }
  411. }
  412. return (UNIVERSAL::isa($value, 'ARRAY') ? "@$value" : $value);
  413. }
  414. sub process_foreach {
  415. my $self = shift;
  416. my $index = $self->{'foreach'}->{'count'};
  417. my $text = $self->{'foreach'}->{'text'}->[$index];
  418. my @values;
  419. my $name = $self->{'foreach'}->{'name'}->[$index];
  420. my @cmds;
  421. my $val = $self->{'foreach'}->{'vars'}->[$index];
  422. my $check_for_mixed;
  423. if ($val =~ /^((\w+),\s*)?flag_overrides\((.*)\)$/) {
  424. ## If the user did not provide a name we have to pick one otherwise
  425. ## there would be no way to access the foreach values.
  426. $name = (defined $2 ? $2 : '__unnamed__');
  427. ## Now check to see if there were overrides for this value. If there
  428. ## were, convert them into an array (if necessary) and continue
  429. ## processing.
  430. $val = $self->get_flag_overrides($3);
  431. if (defined $val) {
  432. $val = $self->create_array($val) if (!UNIVERSAL::isa($val, 'ARRAY'));
  433. @values = @$val;
  434. }
  435. }
  436. else {
  437. ## Pull out modifying commands first
  438. while($val =~ /(\w+)\((.+)\)/) {
  439. my $cmd = $1;
  440. $val = $2;
  441. if (($keywords{$cmd} & $perform_type) != 0) {
  442. push(@cmds, 'perform_' . $cmd);
  443. if (($keywords{$cmd} & $perform_no_eval_type) != 0) {
  444. my @params = $self->split_parameters($val);
  445. $val = \@params;
  446. last;
  447. }
  448. }
  449. else {
  450. $self->warning("Unable to use $cmd in foreach (no perform_ method).");
  451. }
  452. }
  453. ## Get the values for all of the variable names
  454. ## contained within the foreach
  455. if (UNIVERSAL::isa($val, 'ARRAY')) {
  456. @values = @$val;
  457. }
  458. else {
  459. my $names = $self->create_array($val);
  460. foreach my $n (@$names) {
  461. my $vals = $self->get_value($n);
  462. if (defined $vals && $vals ne '') {
  463. if (!UNIVERSAL::isa($vals, 'ARRAY')) {
  464. $vals = $self->create_array($vals);
  465. }
  466. push(@values, @$vals);
  467. }
  468. if (!defined $name) {
  469. $name = $n;
  470. $name =~ s/s$//;
  471. }
  472. ## We only want to check for the mixing of scalar and hash
  473. ## variables if the variable name is not a keyword (or the
  474. ## special 'features' template variable).
  475. if (!$check_for_mixed &&
  476. !$self->{'prjc'}->is_keyword($n) && $n ne 'features') {
  477. $check_for_mixed = 1;
  478. }
  479. }
  480. }
  481. }
  482. ## Perform the commands on the built up @values
  483. foreach my $cmd (reverse @cmds) {
  484. @values = $self->$cmd(\@values);
  485. }
  486. ## Reset the text (it will be regenerated by calling parse_line
  487. $self->{'foreach'}->{'text'}->[$index] = '';
  488. if (defined $values[0]) {
  489. my $scope = $self->{'foreach'}->{'scope'}->[$index];
  490. my $base = $self->{'foreach'}->{'base'}->[$index];
  491. $$scope{'forlast'} = '';
  492. $$scope{'fornotlast'} = 1;
  493. $$scope{'forfirst'} = 1;
  494. $$scope{'fornotfirst'} = '';
  495. ## If the foreach values are mixed (HASH and SCALAR), then
  496. ## remove the SCALAR values.
  497. if ($check_for_mixed) {
  498. my %mixed;
  499. my $mixed = 0;
  500. foreach my $mval (@values) {
  501. $mixed{$mval} = $self->set_current_values($mval);
  502. $mixed |= $mixed{$mval};
  503. }
  504. if ($mixed) {
  505. my @nvalues;
  506. foreach my $key (sort keys %mixed) {
  507. push(@nvalues, $key) if ($mixed{$key});
  508. }
  509. ## Set the new values only if they are different
  510. ## from the original (except for order).
  511. my @sorted = sort(@values);
  512. @values = @nvalues if (@sorted != @nvalues);
  513. }
  514. }
  515. for(my $i = 0; $i <= $#values; ++$i) {
  516. my $value = $values[$i];
  517. ## Set the corresponding values in the temporary scope
  518. $self->set_current_values($value);
  519. ## Set the special values that only exist
  520. ## within a foreach
  521. if ($i != 0) {
  522. $$scope{'forfirst'} = '';
  523. $$scope{'fornotfirst'} = 1;
  524. }
  525. if ($i == $#values) {
  526. $$scope{'forlast'} = 1;
  527. $$scope{'fornotlast'} = '';
  528. }
  529. $$scope{'forcount'} = $i + $base;
  530. ## We don't use adjust_value here because these names
  531. ## are generated from a foreach and should not be adjusted.
  532. $$scope{$name} = $value;
  533. ## A tiny hack for VC7
  534. if ($name eq 'configuration' &&
  535. $self->get_value_with_default('platform') ne '') {
  536. $self->{'prjc'}->update_project_info($self, 1,
  537. ['configuration', 'platform'],
  538. '|');
  539. }
  540. ## Now parse the line of text, each time
  541. ## with different values
  542. ++$self->{'foreach'}->{'processing'};
  543. my($status, $error) = $self->parse_line(undef, $text);
  544. --$self->{'foreach'}->{'processing'};
  545. return $error if (defined $error);
  546. }
  547. }
  548. return undef;
  549. }
  550. sub generic_handle {
  551. my($self, $func, $str) = @_;
  552. if (defined $str) {
  553. my $val = $self->$func([$str]);
  554. if (defined $val) {
  555. $self->append_current($val);
  556. }
  557. else {
  558. $self->append_current(0);
  559. }
  560. }
  561. }
  562. sub handle_endif {
  563. my($self, $name) = @_;
  564. my $end = pop(@{$self->{'sstack'}});
  565. pop(@{$self->{'lstack'}});
  566. if (!defined $end) {
  567. return "Unmatched $name";
  568. }
  569. else {
  570. my $in = index($end, $name);
  571. if ($in == 0) {
  572. $self->{'if_skip'} = 0;
  573. }
  574. elsif ($in == -1) {
  575. return "Unmatched $name";
  576. }
  577. }
  578. return undef;
  579. }
  580. sub handle_endfor {
  581. my($self, $name) = @_;
  582. my $end = pop(@{$self->{'sstack'}});
  583. pop(@{$self->{'lstack'}});
  584. if (!defined $end) {
  585. return "Unmatched $name";
  586. }
  587. else {
  588. my $in = index($end, $name);
  589. if ($in == 0) {
  590. my $index = $self->{'foreach'}->{'count'};
  591. my $error = $self->process_foreach();
  592. if (!defined $error) {
  593. --$self->{'foreach'}->{'count'};
  594. $self->append_current($self->{'foreach'}->{'text'}->[$index]);
  595. }
  596. return $error;
  597. }
  598. elsif ($in == -1) {
  599. return "Unmatched $name";
  600. }
  601. }
  602. return undef;
  603. }
  604. sub get_flag_overrides {
  605. my($self, $name) = @_;
  606. my $type;
  607. ## Split the name and type parameters
  608. ($name, $type) = split(/,\s*/, $name);
  609. my $file = $self->get_value($name);
  610. if (defined $file) {
  611. ## Save the name prefix (if there is one) for
  612. ## command parameter conversion at the end
  613. my $pre;
  614. if ($name =~ /^(\w+)->/) {
  615. $pre = $1;
  616. ## Replace the custom_type key with the actual custom type
  617. if ($pre eq 'custom_type') {
  618. my $ct = $self->get_value($pre);
  619. $name = $ct if (defined $ct);
  620. }
  621. elsif ($pre =~ /^grouped_(.*_file)$/) {
  622. $name = $1;
  623. }
  624. }
  625. my $fo = $self->{'prjc'}->{'flag_overrides'};
  626. my $key = (defined $$fo{$name . 's'} ? $name . 's' :
  627. (defined $$fo{$name} ? $name : undef));
  628. if (defined $key) {
  629. ## Convert the file name into a unix style file name
  630. my $ustyle = $file;
  631. $ustyle =~ s/\\/\//g if ($self->{'cslashes'});
  632. ## Save the directory portion for checking in the foreach
  633. my $dir = $self->mpc_dirname($ustyle);
  634. my $of = (defined $$fo{$key}->{$ustyle} ? $ustyle :
  635. (defined $$fo{$key}->{$dir} ? $dir : undef));
  636. if (defined $of) {
  637. my $prjc = $self->{'prjc'};
  638. foreach my $aname (@{$prjc->{'matching_assignments'}->{$key}}) {
  639. if ($aname eq $type && defined $$fo{$key}->{$of}->{$aname}) {
  640. my $value = $$fo{$key}->{$of}->{$aname};
  641. ## If the name that we're overriding has a value and
  642. ## requires parameters, then we will convert all of the
  643. ## pseudo variables and provide parameters.
  644. if (defined $pre && $prjc->requires_parameters($type)) {
  645. $value = $prjc->convert_command_parameters(
  646. $key, $value,
  647. $self->prepare_parameters($pre));
  648. }
  649. return $prjc->relative($value);
  650. }
  651. }
  652. }
  653. }
  654. }
  655. return undef;
  656. }
  657. sub get_multiple {
  658. my($self, $name) = @_;
  659. return $self->doif_multiple(
  660. $self->create_array($self->get_value_with_default($name)));
  661. }
  662. sub doif_multiple {
  663. my($self, $value) = @_;
  664. return defined $value ? (scalar(@$value) > 1) : undef;
  665. }
  666. sub handle_multiple {
  667. my($self, $name) = @_;
  668. my $val = $self->get_value_with_default($name);
  669. if (defined $val) {
  670. my $array = $self->create_array($val);
  671. $self->append_current(scalar(@$array));
  672. }
  673. else {
  674. $self->append_current(0);
  675. }
  676. }
  677. sub get_starts_with {
  678. my($self, $str) = @_;
  679. return $self->doif_starts_with([$str]);
  680. }
  681. sub doif_starts_with {
  682. my($self, $val) = @_;
  683. if (defined $val) {
  684. my($name, $pattern) = $self->split_parameters("@$val");
  685. if (defined $name && defined $pattern) {
  686. return ($self->get_value_with_default($name) =~ /^$pattern/);
  687. }
  688. }
  689. return undef;
  690. }
  691. sub handle_starts_with {
  692. my($self, $str) = @_;
  693. $self->generic_handle('doif_starts_with', $str);
  694. }
  695. sub get_ends_with {
  696. my($self, $str) = @_;
  697. return $self->doif_ends_with([$str]);
  698. }
  699. sub doif_ends_with {
  700. my($self, $val) = @_;
  701. if (defined $val) {
  702. my($name, $pattern) = $self->split_parameters("@$val");
  703. if (defined $name && defined $pattern) {
  704. return ($self->get_value_with_default($name) =~ /$pattern$/);
  705. }
  706. }
  707. return undef;
  708. }
  709. sub handle_ends_with {
  710. my($self, $str) = @_;
  711. $self->generic_handle('doif_ends_with', $str);
  712. }
  713. sub handle_keyname_used {
  714. my($self, $str) = @_;
  715. if (defined $str) {
  716. my($name, $key) = $self->split_parameters($str);
  717. my $file = $self->get_value_with_default($name);
  718. if (defined $self->{'keyname_used'}->{$file}->{$key}) {
  719. $self->append_current($self->{'keyname_used'}->{$file}->{$key}++);
  720. }
  721. else {
  722. $self->{'keyname_used'}->{$file}->{$key} = 1;
  723. }
  724. }
  725. }
  726. sub handle_scope {
  727. my($self, $str) = @_;
  728. if (defined $str) {
  729. my($state, $func, $param) = $self->split_parameters($str);
  730. if (defined $state) {
  731. my $pscope;
  732. my $scope = $self->{'scopes'};
  733. while(defined $$scope{'scope'}) {
  734. $pscope = $scope;
  735. $scope = $$scope{'scope'};
  736. }
  737. if ($state eq 'enter') {
  738. if (defined $func) {
  739. $param = '' if (!defined $param);
  740. $$scope{'scope'}->{$func} = [$self->process_special($param),
  741. $_[0]->{'foreach'}->{'count'}];
  742. }
  743. else {
  744. $self->warning("The enter scope function requires a parameter.");
  745. }
  746. }
  747. elsif ($state eq 'leave') {
  748. if (defined $pscope) {
  749. delete $$pscope{'scope'};
  750. }
  751. else {
  752. $self->warning("leave scope function encountered without an enter.");
  753. }
  754. }
  755. else {
  756. $self->warning("Unrecognized scope function parameter: $state.");
  757. }
  758. }
  759. else {
  760. $self->warning("The scope function requires 1 to 3 parameters.");
  761. }
  762. }
  763. }
  764. sub get_has_extension {
  765. my($self, $str) = @_;
  766. return $self->doif_has_extension([$str]);
  767. }
  768. sub doif_has_extension {
  769. my($self, $val) = @_;
  770. if (defined $val) {
  771. return ($self->tp_basename(
  772. $self->get_value_with_default("@$val")) =~ /\.[^\.]*$/);
  773. }
  774. return undef;
  775. }
  776. sub handle_has_extension {
  777. my($self, $str) = @_;
  778. $self->generic_handle('doif_has_extension', $str);
  779. }
  780. sub get_contains {
  781. my($self, $str) = @_;
  782. return $self->doif_contains([$str]);
  783. }
  784. sub doif_contains {
  785. my($self, $val) = @_;
  786. if (defined $val) {
  787. my($name, $pattern) = $self->split_parameters("@$val");
  788. if (defined $name && defined $pattern) {
  789. return ($self->get_value_with_default($name) =~ /$pattern/);
  790. }
  791. }
  792. return undef;
  793. }
  794. sub handle_contains {
  795. my($self, $str) = @_;
  796. $self->generic_handle('doif_contains', $str);
  797. }
  798. sub get_subst {
  799. my($self, $str) = @_;
  800. return $self->doif_subst([$str]);
  801. }
  802. sub doif_subst {
  803. my($self, $val) = @_;
  804. if (defined $val) {
  805. my($name, $pattern, $replacement) = $self->split_parameters("@$val");
  806. if (defined $name && defined $pattern && defined $replacement) {
  807. my $result = $self->get_value_with_default($name);
  808. $result =~ s/$pattern/$replacement/g;
  809. return $result;
  810. }
  811. }
  812. return undef;
  813. }
  814. sub handle_subst {
  815. my($self, $str) = @_;
  816. $self->generic_handle('doif_subst', $str);
  817. }
  818. sub get_remove_from {
  819. my($self, $str) = @_;
  820. return $self->doif_remove_from($str);
  821. }
  822. sub doif_remove_from {
  823. my($self, $str) = @_;
  824. my @params = $self->split_parameters($str);
  825. my @removed = $self->perform_remove_from(\@params);
  826. return (defined $removed[0] ? 1 : undef);
  827. }
  828. sub perform_remove_from {
  829. my($self, $val) = @_;
  830. my($source, $pattern, $target, $tremove) = @$val;
  831. ## $source should be a component name (e.g., source_files,
  832. ## header_files, etc.) $target is a variable name
  833. ## $pattern and $tremove are optional; $pattern is a partial regular
  834. ## expression to match the end of the files found from $source. The
  835. ## beginning of the regular expression is made from $target by removing
  836. ## $tremove from the end of it.
  837. if (defined $source && defined $target &&
  838. defined $self->{'values'}->{$source}) {
  839. my $tval = $self->get_value_with_default($target);
  840. if (defined $tval) {
  841. $tval =~ s/$tremove$// if (defined $tremove);
  842. $tval = $self->escape_regex_special($tval);
  843. my @removed;
  844. my $max = scalar(@{$self->{'values'}->{$source}});
  845. for(my $i = 0; $i < $max;) {
  846. if ($self->{'values'}->{$source}->[$i] =~ /^$tval$pattern$/) {
  847. push(@removed, splice(@{$self->{'values'}->{$source}}, $i, 1));
  848. $max--;
  849. }
  850. else {
  851. $i++;
  852. }
  853. }
  854. return @removed;
  855. }
  856. }
  857. return ();
  858. }
  859. sub handle_remove_from {
  860. my($self, $str) = @_;
  861. if (defined $str) {
  862. my @params = $self->split_parameters($str);
  863. my $val = $self->perform_remove_from(\@params);
  864. $self->append_current("@$val") if (defined $val);
  865. }
  866. }
  867. sub get_compares {
  868. my($self, $str) = @_;
  869. return $self->doif_compares([$str]);
  870. }
  871. sub doif_compares {
  872. my($self, $val) = @_;
  873. if (defined $val) {
  874. my($name, $pattern) = $self->split_parameters("@$val");
  875. if (defined $name && defined $pattern) {
  876. return ($self->get_value_with_default($name) eq $pattern);
  877. }
  878. }
  879. return undef;
  880. }
  881. sub handle_compares {
  882. my($self, $str) = @_;
  883. $self->generic_handle('doif_compares', $str);
  884. }
  885. sub get_vars_equal {
  886. my($self, $str) = @_;
  887. return $self->doif_vars_equal([$str]);
  888. }
  889. sub doif_vars_equal {
  890. my($self, $val) = @_;
  891. if (defined $val) {
  892. my($var1, $var2) = $self->split_parameters("@$val");
  893. if (defined $var1 && defined $var2) {
  894. return ($self->get_value_with_default($var1) eq $self->get_value_with_default($var2));
  895. }
  896. }
  897. return undef;
  898. }
  899. sub handle_vars_equal {
  900. my($self, $str) = @_;
  901. $self->generic_handle('doif_vars_equal', $str);
  902. }
  903. sub get_reverse {
  904. my($self, $name) = @_;
  905. my $value = $self->get_value_with_default($name);
  906. if (defined $value) {
  907. my @array = $self->perform_reverse($self->create_array($value));
  908. return \@array;
  909. }
  910. return undef;
  911. }
  912. sub perform_reverse {
  913. my($self, $value) = @_;
  914. return reverse(@$value);
  915. }
  916. sub handle_reverse {
  917. my($self, $name) = @_;
  918. my $val = $self->get_value_with_default($name);
  919. if (defined $val) {
  920. my @array = $self->perform_reverse($self->create_array($val));
  921. $self->append_current("@array");
  922. }
  923. }
  924. sub get_sort {
  925. my($self, $name) = @_;
  926. my $value = $self->get_value_with_default($name);
  927. if (defined $value) {
  928. my @array = $self->perform_sort($self->create_array($value));
  929. return \@array;
  930. }
  931. return undef;
  932. }
  933. sub perform_sort {
  934. my($self, $value) = @_;
  935. return sort(@$value);
  936. }
  937. sub handle_sort {
  938. my($self, $name) = @_;
  939. my $val = $self->get_value_with_default($name);
  940. if (defined $val) {
  941. my @array = $self->perform_sort($self->create_array($val));
  942. $self->append_current("@array");
  943. }
  944. }
  945. sub get_uniq {
  946. my($self, $name) = @_;
  947. my $value = $self->get_value_with_default($name);
  948. if (defined $value) {
  949. my @array = $self->perform_uniq($self->create_array($value));
  950. return \@array;
  951. }
  952. return undef;
  953. }
  954. sub perform_uniq {
  955. my($self, $value) = @_;
  956. my %value;
  957. @value{@$value} = ();
  958. return sort(keys %value);
  959. }
  960. sub handle_uniq {
  961. my($self, $name) = @_;
  962. my $val = $self->get_value_with_default($name);
  963. if (defined $val) {
  964. my @array = $self->perform_uniq($self->create_array($val));
  965. $self->append_current("@array");
  966. }
  967. }
  968. sub process_compound_if {
  969. my($self, $str) = @_;
  970. if (index($str, '||') >= 0) {
  971. my $ret = 0;
  972. foreach my $v (split(/\s*\|\|\s*/, $str)) {
  973. $ret |= $self->process_compound_if($v);
  974. return 1 if ($ret != 0);
  975. }
  976. return 0;
  977. }
  978. elsif (index($str, '&&') >= 0) {
  979. my $ret = 1;
  980. foreach my $v (split(/\s*\&\&\s*/, $str)) {
  981. $ret &&= $self->process_compound_if($v);
  982. return 0 if ($ret == 0);
  983. }
  984. return 1;
  985. }
  986. else {
  987. ## See if we need to reverse the return value
  988. my $not = 0;
  989. if ($str =~ /^!+(.*)/) {
  990. $not = 1;
  991. $str = $1;
  992. }
  993. ## Get the value based on the string
  994. my @cmds;
  995. my $val;
  996. while($str =~ /(\w+)\((.+)\)(.*)/) {
  997. if ($3 eq '') {
  998. push(@cmds, $1);
  999. $str = $2;
  1000. }
  1001. else {
  1002. ## If there is something trailing the closing parenthesis then
  1003. ## the whole thing is considered a parameter to the first
  1004. ## function.
  1005. last;
  1006. }
  1007. }
  1008. if (defined $cmds[0]) {
  1009. ## Start out calling get_xxx on the string
  1010. my $type = $get_type;
  1011. my $prefix = 'get_';
  1012. $val = $str;
  1013. ## If there is only one command, we have to add it to the list
  1014. ## again so that we can get the variable value and then use
  1015. ## the doif_ version to test it, unless the get_ function
  1016. ## also performs the doif_ functionality.
  1017. if ($#cmds == 0 && defined $keywords{$cmds[0]} &&
  1018. ($keywords{$cmds[0]} & $doif_type) != 0 &&
  1019. ($keywords{$cmds[0]} & $get_combined_type) == 0) {
  1020. push(@cmds, $cmds[0]);
  1021. }
  1022. foreach my $cmd (reverse @cmds) {
  1023. if (defined $keywords{$cmd} && ($keywords{$cmd} & $type) != 0) {
  1024. my $func = "$prefix$cmd";
  1025. $val = $self->$func($val);
  1026. ## Now that we have a value, we need to switch over
  1027. ## to calling doif_xxx
  1028. $type = $doif_type;
  1029. $prefix = 'doif_';
  1030. }
  1031. else {
  1032. $self->warning("Unable to use $cmd in if (no $prefix method).");
  1033. }
  1034. }
  1035. }
  1036. else {
  1037. $val = $self->get_value($str);
  1038. }
  1039. ## See if any portion of the value is defined and not empty
  1040. my $ret = 0;
  1041. if (defined $val) {
  1042. if (UNIVERSAL::isa($val, 'ARRAY')) {
  1043. foreach my $v (@$val) {
  1044. if ($v ne '') {
  1045. $ret = 1;
  1046. last;
  1047. }
  1048. }
  1049. }
  1050. elsif ($val ne '') {
  1051. $ret = 1;
  1052. }
  1053. }
  1054. return ($not ? !$ret : $ret);
  1055. }
  1056. }
  1057. sub handle_if {
  1058. my($self, $val) = @_;
  1059. my $name = 'endif';
  1060. push(@{$self->{'lstack'}},
  1061. "<%if($val)%> (" . $self->get_line_number() . '?)');
  1062. if ($self->{'if_skip'}) {
  1063. push(@{$self->{'sstack'}}, "*$name");
  1064. }
  1065. else {
  1066. ## Determine if we are skipping the portion of this if statement
  1067. ## $val will always be defined since we won't get into this method
  1068. ## without properly parsing the if statement.
  1069. $self->{'if_skip'} = !$self->process_compound_if($val);
  1070. push(@{$self->{'sstack'}}, $name);
  1071. }
  1072. }
  1073. sub handle_else {
  1074. my $self = shift;
  1075. my @scopy = @{$self->{'sstack'}};
  1076. my $index = index($scopy[$#scopy], 'endif');
  1077. if ($index >= 0) {
  1078. if ($index == 0) {
  1079. $self->{'if_skip'} ^= 1;
  1080. }
  1081. $self->{'sstack'}->[$#scopy] .= ':';
  1082. }
  1083. return 'Unmatched else' if (($self->{'sstack'}->[$#scopy] =~ tr/:/:/) > 1);
  1084. return undef;
  1085. }
  1086. sub handle_foreach {
  1087. my $self = shift;
  1088. my $val = lc(shift);
  1089. my $name = 'endfor';
  1090. my $errorString;
  1091. push(@{$self->{'lstack'}}, $self->get_line_number());
  1092. if (!$self->{'if_skip'}) {
  1093. my $base = 1;
  1094. my $vname;
  1095. if ($val =~ /flag_overrides\([^\)]+\)/) {
  1096. }
  1097. elsif ($val =~ /([^,]*),(.*)/) {
  1098. $vname = $1;
  1099. $val = $2;
  1100. $vname =~ s/^\s+//;
  1101. $vname =~ s/\s+$//;
  1102. $val =~ s/^\s+//;
  1103. $val =~ s/\s+$//;
  1104. if ($vname eq '') {
  1105. $errorString = 'The foreach variable name is not valid';
  1106. }
  1107. if ($val =~ /([^,]*),(.*)/) {
  1108. $base = $1;
  1109. $val = $2;
  1110. $base =~ s/^\s+//;
  1111. $base =~ s/\s+$//;
  1112. $val =~ s/^\s+//;
  1113. $val =~ s/\s+$//;
  1114. if ($base !~ /^\d+$/) {
  1115. $errorString = 'The forcount specified is not a valid number';
  1116. }
  1117. }
  1118. elsif ($vname =~ /^\d+$/) {
  1119. $base = $vname;
  1120. $vname = undef;
  1121. }
  1122. ## Due to the way flag_overrides works, we can't allow
  1123. ## the user to name the foreach variable when dealing
  1124. ## with variables that can be used with the -> operator
  1125. if (defined $vname) {
  1126. foreach my $ref (keys %arrow_op_ref) {
  1127. my $name_re = $ref . 's';
  1128. if ($val =~ /^$ref\->/ || $val =~ /^$name_re$/) {
  1129. $errorString = 'The foreach variable can not be ' .
  1130. 'named when dealing with ' .
  1131. $arrow_op_ref{$ref};
  1132. }
  1133. }
  1134. }
  1135. }
  1136. push(@{$self->{'sstack'}}, $name);
  1137. my $index = ++$self->{'foreach'}->{'count'};
  1138. $self->{'foreach'}->{'base'}->[$index] = $base;
  1139. $self->{'foreach'}->{'name'}->[$index] = $vname;
  1140. $self->{'foreach'}->{'vars'}->[$index] = $val;
  1141. $self->{'foreach'}->{'text'}->[$index] = '';
  1142. $self->{'foreach'}->{'scope'}->[$index] = {};
  1143. $self->{'foreach'}->{'scope_name'}->[$index] = undef;
  1144. }
  1145. else {
  1146. push(@{$self->{'sstack'}}, "*$name");
  1147. }
  1148. return $errorString;
  1149. }
  1150. sub handle_special {
  1151. my($self, $name, $val) = @_;
  1152. ## If $name (fornotlast, forfirst, etc.) is set to 1
  1153. ## Then we append the $val onto the current string that's
  1154. ## being built.
  1155. $self->append_current($val) if ($self->get_value($name));
  1156. }
  1157. sub get_uc {
  1158. my($self, $name) = @_;
  1159. return uc($self->get_value_with_default($name));
  1160. }
  1161. sub handle_uc {
  1162. my($self, $name) = @_;
  1163. $self->append_current($self->get_uc($name));
  1164. }
  1165. sub perform_uc {
  1166. my($self, $value) = @_;
  1167. my @val;
  1168. foreach my $val (@$value) {
  1169. push(@val, uc($val));
  1170. }
  1171. return @val;
  1172. }
  1173. sub get_lc {
  1174. my($self, $name) = @_;
  1175. return lc($self->get_value_with_default($name));
  1176. }
  1177. sub handle_lc {
  1178. my($self, $name) = @_;
  1179. $self->append_current($self->get_lc($name));
  1180. }
  1181. sub perform_lc {
  1182. my($self, $value) = @_;
  1183. my @val;
  1184. foreach my $val (@$value) {
  1185. push(@val, lc($val));
  1186. }
  1187. return @val;
  1188. }
  1189. sub handle_ucw {
  1190. my($self, $name) = @_;
  1191. my $val = $self->get_value_with_default($name);
  1192. substr($val, 0, 1) = uc(substr($val, 0, 1));
  1193. while($val =~ /[_\s]([a-z])/) {
  1194. my $uc = uc($1);
  1195. $val =~ s/[_\s][a-z]/ $uc/;
  1196. }
  1197. $self->append_current($val);
  1198. }
  1199. sub actual_normalize {
  1200. $_[1] =~ tr/ \t\/\\\-$()./_/;
  1201. return $_[1];
  1202. }
  1203. sub perform_normalize {
  1204. my($self, $value) = @_;
  1205. my @val;
  1206. foreach my $val (@$value) {
  1207. push(@val, $self->actual_normalize($val));
  1208. }
  1209. return @val;
  1210. }
  1211. sub get_normalize {
  1212. my($self, $name) = @_;
  1213. return $self->actual_normalize($self->get_value_with_default($name));
  1214. }
  1215. sub handle_normalize {
  1216. my($self, $name) = @_;
  1217. $self->append_current($self->get_normalize($name));
  1218. }
  1219. sub actual_noextension {
  1220. $_[1] =~ s/\.[^\.]*$//;
  1221. return $_[1];
  1222. }
  1223. sub perform_noextension {
  1224. my($self, $value) = @_;
  1225. my @val;
  1226. foreach my $val (@$value) {
  1227. push(@val, $self->actual_noextension($val));
  1228. }
  1229. return @val;
  1230. }
  1231. sub get_noextension {
  1232. my($self, $name) = @_;
  1233. return $self->actual_noextension($self->get_value_with_default($name));
  1234. }
  1235. sub handle_noextension {
  1236. my($self, $name) = @_;
  1237. $self->append_current($self->get_noextension($name));
  1238. }
  1239. sub perform_full_path {
  1240. my($self, $value) = @_;
  1241. my @val;
  1242. foreach my $val (@$value) {
  1243. push(@val, $self->actual_full_path($val));
  1244. }
  1245. return @val;
  1246. }
  1247. sub get_full_path {
  1248. my($self, $name) = @_;
  1249. return $self->actual_full_path($self->get_value_with_default($name));
  1250. }
  1251. sub actual_full_path {
  1252. my($self, $value) = @_;
  1253. ## Expand all defined env vars
  1254. $value =~ s/\$\((\w+)\)/$ENV{$1} || '$(' . $1 . ')'/ge;
  1255. ## If we expanded all env vars, get absolute path
  1256. if ($value =~ /\$\(\w+\)/) {
  1257. $self->{'error_in_handle'} = "<%full_path%> couldn't expand " .
  1258. "environment variables in $value";
  1259. return $value;
  1260. }
  1261. ## Always convert the slashes since they may be in the OS native
  1262. ## format and we need them in UNIX format.
  1263. $value =~ s/\\/\//g;
  1264. my $dir = $self->mpc_dirname($value);
  1265. if (-e $dir) {
  1266. $dir = Cwd::abs_path($dir);
  1267. }
  1268. elsif ($self->{'prjc'}->path_is_relative($dir)) {
  1269. ## If the directory is is not already an absolute path, then we will
  1270. ## assume that the directory is relative to the current directory
  1271. ## (which will be the location of the MPC file).
  1272. $dir = $self->getcwd() . '/' . $dir;
  1273. }
  1274. ## Create the full path value and convert the slashes if necessary.
  1275. $value = $dir . '/' . $self->mpc_basename($value);
  1276. $value =~ s/\//\\/g if ($self->{'cslashes'});
  1277. return $value;
  1278. }
  1279. sub handle_full_path {
  1280. my($self, $name) = @_;
  1281. my $val = $self->get_value_with_default($name);
  1282. $self->append_current($self->actual_full_path($val));
  1283. }
  1284. sub perform_extensions {
  1285. my($self, $value) = @_;
  1286. my @val;
  1287. foreach my $val (@$value) {
  1288. push(@val, $self->{'prjc'}->get_component_extensions($val));
  1289. }
  1290. return @val;
  1291. }
  1292. sub handle_extensions {
  1293. my($self, $name) = @_;
  1294. my @val = $self->perform_extensions([$name]);
  1295. $self->append_current("@val");
  1296. }
  1297. sub evaluate_nested_functions {
  1298. my($self, $funcname, $args) = @_;
  1299. my @params = $self->split_parameters($args);
  1300. my @results;
  1301. foreach my $param (@params) {
  1302. my @cmds;
  1303. my $val = $param;
  1304. while($val =~ /(\w+)\((.+)\)/) {
  1305. push(@cmds, $1);
  1306. $val = $2;
  1307. }
  1308. if (scalar @cmds == 0) {
  1309. push @results, $val;
  1310. next;
  1311. }
  1312. my $type = $get_type;
  1313. my $prefix = 'get_';
  1314. foreach my $cmd (reverse @cmds) {
  1315. if (defined $keywords{$cmd} && ($keywords{$cmd} & $type) != 0) {
  1316. my $func = "$prefix$cmd";
  1317. if ($type == $get_type) {
  1318. $val = $self->$func($val);
  1319. $val = [ $val ] if (!UNIVERSAL::isa($val, 'ARRAY'));
  1320. ## Now that we have a value, we need to switch over
  1321. ## to calling perform_xxx
  1322. $type = $perform_type;
  1323. $prefix = 'perform_';
  1324. }
  1325. else {
  1326. my @array = $self->$func($val);
  1327. $val = \@array;
  1328. }
  1329. }
  1330. else {
  1331. $self->warning("Unable to use $cmd in nested " .
  1332. "functions (no $prefix method).");
  1333. }
  1334. }
  1335. push @results, "@$val";
  1336. }
  1337. if (defined $keywords{$funcname} && ($keywords{$funcname} & $perform_type)) {
  1338. my $func = 'perform_' . $funcname;
  1339. my @array = $self->$func(\@results);
  1340. $self->append_current("@array");
  1341. if ($keywords{$funcname} & $post_type) {
  1342. $func = 'post_' . $funcname;
  1343. $self->$func();
  1344. }
  1345. }
  1346. else {
  1347. $self->warning("Unable to use $funcname in nested " .
  1348. "functions (no perform_ method).");
  1349. }
  1350. }
  1351. sub perform_dirname {
  1352. my($self, $value) = @_;
  1353. my @val;
  1354. foreach my $val (@$value) {
  1355. push(@val, $self->tp_dirname($val));
  1356. }
  1357. return @val;
  1358. }
  1359. sub get_dirname {
  1360. my($self, $name) = @_;
  1361. return $self->tp_dirname($self->get_value_with_default($name));
  1362. }
  1363. sub doif_dirname {
  1364. my($self, $value) = @_;
  1365. if (defined $value) {
  1366. $value = $self->tp_dirname($value);
  1367. return ($value ne '.');
  1368. }
  1369. return undef;
  1370. }
  1371. sub handle_dirname {
  1372. my($self, $name) = @_;
  1373. $self->append_current(
  1374. $self->tp_dirname($self->get_value_with_default($name)));
  1375. }
  1376. sub perform_basename {
  1377. my($self, $value) = @_;
  1378. my @val;
  1379. foreach my $val (@$value) {
  1380. push(@val, $self->tp_basename($val));
  1381. }
  1382. return @val;
  1383. }
  1384. sub get_basename {
  1385. my($self, $name) = @_;
  1386. return $self->tp_basename($self->get_value_with_default($name));
  1387. }
  1388. sub doif_basename {
  1389. my($self, $value) = @_;
  1390. if (defined $value) {
  1391. $value = $self->tp_basename($value);
  1392. return ($value ne '.');
  1393. }
  1394. return undef;
  1395. }
  1396. sub handle_basename {
  1397. my($self, $name) = @_;
  1398. $self->append_current(
  1399. $self->tp_basename($self->get_value_with_default($name)));
  1400. }
  1401. sub handle_basenoextension {
  1402. my($self, $name) = @_;
  1403. my $val = $self->tp_basename($self->get_value_with_default($name));
  1404. $val =~ s/\.[^\.]*$//;
  1405. $self->append_current($val);
  1406. }
  1407. sub handle_flag_overrides {
  1408. my($self, $name) = @_;
  1409. my $value = $self->get_flag_overrides($name);
  1410. $self->append_current(UNIVERSAL::isa($value, 'ARRAY') ?
  1411. "@$value" : $value) if (defined $value);
  1412. }
  1413. sub handle_marker {
  1414. my($self, $name) = @_;
  1415. my $val = $self->{'prjc'}->get_verbatim($name);
  1416. $self->append_current($val) if (defined $val);
  1417. }
  1418. sub handle_eval {
  1419. my($self, $name) = @_;
  1420. my $val = $self->get_value_with_default($name);
  1421. if (defined $val) {
  1422. if (index($val, "<%eval($name)%>") >= 0) {
  1423. $self->warning("Infinite recursion detected in '$name'.");
  1424. }
  1425. else {
  1426. ## Enter the eval state
  1427. ++$self->{'eval'};
  1428. ## Parse the eval line
  1429. my($status, $error) = $self->parse_line(undef, $val);
  1430. if ($status) {
  1431. $self->{'built'} .= $self->{'eval_str'};
  1432. }
  1433. else {
  1434. $self->warning($error);
  1435. }
  1436. ## Leave the eval state
  1437. --$self->{'eval'};
  1438. $self->{'eval_str'} = '';
  1439. }
  1440. }
  1441. }
  1442. sub handle_pseudo {
  1443. my($self, $name) = @_;
  1444. $self->append_current($self->{'cmds'}->{$name});
  1445. }
  1446. sub get_duplicate_index {
  1447. my($self, $name) = @_;
  1448. return $self->doif_duplicate_index($self->get_value_with_default($name));
  1449. }
  1450. sub doif_duplicate_index {
  1451. my($self, $value) = @_;
  1452. if (defined $value) {
  1453. my $base = lc($self->tp_basename($value));
  1454. my $path = $self->validated_dirname($value);
  1455. if (!defined $self->{'dupfiles'}->{$base}) {
  1456. $self->{'dupfiles'}->{$base} = [$path];
  1457. }
  1458. else {
  1459. my $index = 1;
  1460. foreach my $file (@{$self->{'dupfiles'}->{$base}}) {
  1461. return $index if ($file eq $path);
  1462. ++$index;
  1463. }
  1464. push(@{$self->{'dupfiles'}->{$base}}, $path);
  1465. return 1;
  1466. }
  1467. }
  1468. return undef;
  1469. }
  1470. sub handle_duplicate_index {
  1471. my($self, $name) = @_;
  1472. my $value = $self->doif_duplicate_index(
  1473. $self->get_value_with_default($name));
  1474. $self->append_current($value) if (defined $value);
  1475. }
  1476. sub actual_transdir {
  1477. my($self, $value) = @_;
  1478. if ($value =~ /([\/\\])/) {
  1479. return $self->{'prjc'}->translate_directory(
  1480. $self->tp_dirname($value)) . $1;
  1481. }
  1482. return undef;
  1483. }
  1484. sub get_transdir {
  1485. my($self, $name) = @_;
  1486. return $self->actual_transdir($self->get_value_with_default($name));
  1487. }
  1488. sub doif_transdir {
  1489. my($self, $value) = @_;
  1490. return (defined $value ? $self->actual_transdir($value) : undef);
  1491. }
  1492. sub handle_transdir {
  1493. my($self, $name) = @_;
  1494. my $value = $self->actual_transdir($self->get_value_with_default($name));
  1495. $self->append_current($value) if (defined $value);
  1496. }
  1497. sub handle_create_aux_file {
  1498. my $self = shift;
  1499. my @fname = $self->perform_create_aux_file([$self->split_parameters(shift)]);
  1500. $self->append_current($fname[0]);
  1501. $self->post_create_aux_file();
  1502. }
  1503. sub post_create_aux_file {
  1504. my $self = shift;
  1505. $self->{'aux_file'} = $self->{'aux_temp'};
  1506. $self->{'aux_temp'} = undef;
  1507. }
  1508. sub perform_create_aux_file {
  1509. my($self, $argsref) = @_;
  1510. if (defined $self->{'aux_file'}) {
  1511. $self->{'error_in_handle'} = "Can't nest create_aux_file commands.";
  1512. return undef;
  1513. }
  1514. my $fname = '';
  1515. foreach my $arg (@$argsref) {
  1516. my $val = $self->get_value($arg);
  1517. $fname .= defined $val ?
  1518. (UNIVERSAL::isa($val, 'ARRAY') ? join('_', @$val) : $val) : $arg;
  1519. }
  1520. my $dir = $self->mpc_dirname($self->{'prjc'}->get_outdir() . '/' .
  1521. $self->{'prjc'}->{'assign'}->{'project_file'});
  1522. $dir .= '/' . $self->mpc_dirname($fname) if ($fname =~ /[\/\\]/);
  1523. $self->{'aux_temp'} = {'dir' => $dir,
  1524. 'filename' => $self->mpc_basename($fname),
  1525. 'foreach_baseline' => $self->{'foreach'}->{'count'}};
  1526. return $fname;
  1527. }
  1528. sub handle_end_aux_file {
  1529. my $self = shift;
  1530. if (!defined $self->{'aux_file'}) {
  1531. $self->{'error_in_handle'} = 'end_aux_file seen before create_aux_file';
  1532. }
  1533. else {
  1534. my $af = $self->{'aux_file'};
  1535. mkpath($af->{'dir'}, 0, 0777) if ($af->{'dir'} ne '.');
  1536. my $fh = new FileHandle('> ' . $af->{'dir'} . '/' . $af->{'filename'});
  1537. if (defined $fh) {
  1538. print $fh $af->{'text'};
  1539. close($fh);
  1540. }
  1541. else {
  1542. $self->{'error_in_handle'} = "Couldn't open: " . $af->{'dir'} . '/' .
  1543. $af->{'filename'};
  1544. }
  1545. $self->{'aux_file'} = undef;
  1546. }
  1547. }
  1548. sub handle_translate_vars {
  1549. my($self, $arg) = @_;
  1550. my @params = $self->split_parameters($arg);
  1551. $self->append_current($self->perform_translate_vars([@params]));
  1552. }
  1553. sub get_translate_vars {
  1554. my ($self, $str) = @_;
  1555. my @params = $self->split_parameters($str);
  1556. return $self->perform_translate_vars([@params]);
  1557. }
  1558. sub perform_translate_vars {
  1559. my($self, $arg) = @_;
  1560. ## If the first parameter is a template variable with a value, use it.
  1561. ## Otherwise, use the parameter as the value.
  1562. my $val = $self->get_value($arg->[0]);
  1563. $val = $arg->[0] unless defined $val;
  1564. ## If the second optional parameter is provided, use it. Otherwise,
  1565. ## use the operating system found in the command substitution map.
  1566. my $os = (defined $arg->[1] && $arg->[1] ne '') ?
  1567. $arg->[1] : $self->{'prjc'}->{'command_subs'}->{'os'};
  1568. ## Get the variable reference characters based on the operating system
  1569. ## for which we are generating this project.
  1570. my ($pre, $post) = ($os eq 'win32') ? ('%', '%') : ('${', '}');
  1571. ## Replace $() with the environment variable reference characters.
  1572. $val =~ s{\$\(([^)]+)\)([^\s\$]*)}{my ($var, $rest) = ($1, $2);
  1573. $rest =~ s!/!\\!g if $os eq 'win32';

Large files files are truncated, but you can click here to view the full file