source: CMT/HEAD/source/cmt_deps_builder.cxx @ 606

Last change on this file since 606 was 606, checked in by rybkin, 12 years ago

See C.L. 481

  • Property svn:eol-style set to native
File size: 27.2 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// See the complete license in cmt_license.txt "http://www.cecill.info".
5//-----------------------------------------------------------
6
7#include "cmt_deps_builder.h"
8#include "cmt_system.h"
9#include "cmt_use.h"
10#include "cmt_include.h"
11#include "cmt_symbol.h"
12#include "cmt_log.h"
13#include "cmt_error.h"
14
15//
16//  While parsing a C++ file, these are the possible usefull
17// states we can reach.
18//  Each state correspond to a specific state action function.
19//
20enum state_def
21  {
22    at_start,                                // beginning of the file
23    in_line,                                // along a line
24    in_string,                        // inside a quoted string
25    in_char,                                // inside a quoted char
26    in_comment,                        // inside a multi-line comment
27    in_string_comment,        // inside a quoted string in a comment
28    in_char_comment,                // inside a quoted char in a comment
29    in_line_comment                // inside a single-line comment
30  };
31
32//--------------------------------------------------
33static int locate (const cmt_string& name,
34                   const cmt_string& dir_name,
35                   const CmtSystem::cmt_string_vector& include_paths,
36                   const CmtSystem::cmt_string_vector& substitutions,
37                   cmt_string& full_name);
38
39//--------------------------------------------------
40static void build_deps_text (char* text,
41                             const cmt_string& dir_name,
42                             int current_path_index,
43                             const CmtSystem::cmt_string_vector& include_paths,
44                             const CmtSystem::cmt_string_vector& substitutions,
45                             const DepsBuilder::HeaderFilters& header_filters,
46                             CmtSystem::cmt_string_vector& all_deps,
47                             CmtSystem::cmt_string_vector& deps);
48
49//--------------------------------------------------
50static void header_file_action (const char* header_file,
51                                const cmt_string& dir_name,
52                                int current_path_index,
53                                const CmtSystem::cmt_string_vector& include_paths,
54                                const CmtSystem::cmt_string_vector& substitutions,
55                                const DepsBuilder::HeaderFilters& header_filters,
56                                CmtSystem::cmt_string_vector& all_deps,
57                                CmtSystem::cmt_string_vector& deps)
58{
59  Log;
60
61  for (int i = 0; i < all_deps.size (); i++)
62    {
63      const cmt_string& n = all_deps[i];
64
65      log << "CMT> check old header file name=" << n << " against " << header_file << log_endl;
66
67      if (n == header_file) return;
68    }
69
70  all_deps.push_back (header_file);
71
72  cmt_string header_file_path;
73  int path_index = locate (header_file,
74                           dir_name,
75                           include_paths,
76                           substitutions,
77                           header_file_path);
78
79  if (path_index < 0) return;
80
81  static int header_filters_size = header_filters.size ();
82  if (header_filters_size > 0)
83    {
84      // check the filter macros from
85      // find all macros named <package>_header_file_filter
86      // for all those macros, get the regexp and check the matches against the header file name
87      // if any match, select the stamp file instead of the header file
88      // the stamp file might be either a conventional name
89      //         <package>/cmt/cmt_all_headers.stamp
90      // or given in a macro eg <package>_header_stamp_file_name
91      //
92      for (int i = header_filters_size - 1; i >= 0; i--)
93        {
94          cmt_string stamp_file;
95          log << "|header_file_action> header " << header_file_path << " against stamp " << stamp_file << log_endl;
96          if (header_filters[i].use_stamp (header_file_path, stamp_file))
97            {
98              bool included = false;
99              for (int i = deps.size () - 1; i >= 0; i--)
100                {
101                  if (deps[i] == stamp_file)
102                    {
103                      included = true;
104                      break;
105                    }
106                }
107              if (!included) deps.push_back (stamp_file);
108              return;
109            }
110        }
111    }
112
113  log << "CMT> parsing new header file name=" << header_file << log_endl;
114
115///////////////////////////////////////////////////////////////////////////////////////////////////////
116  cmt_string text;
117  if (!text.read (header_file_path))
118    {
119      CmtError::set (CmtError::file_access_error, header_file_path);
120      return;
121    }
122  char* ptr = &text[0];
123  cmt_string new_dir;
124  CmtSystem::dirname (header_file_path, new_dir);
125
126  if (path_index == 0 || path_index == 1)
127    build_deps_text (ptr, new_dir,
128                     current_path_index,
129                     include_paths, substitutions,
130                     header_filters,
131                     all_deps, deps);
132  else
133    build_deps_text (ptr, new_dir,
134                     path_index,
135                     include_paths, substitutions,
136                     header_filters,
137                     all_deps, deps);
138///////////////////////////////////////////////////////////////////////////////////////////////////////
139     
140//path_index >= 0
141
142  cmt_string full_name;
143
144  if (path_index == 1)
145    {
146      full_name = dir_name;
147      full_name += CmtSystem::file_separator ();
148
149      if (current_path_index >= 2)
150        {
151          full_name.replace (include_paths[current_path_index - 2],
152                             substitutions[current_path_index - 2]);
153        }
154    }
155  else if (path_index > 1)
156    {
157      full_name  = substitutions[path_index - 2];
158      full_name += CmtSystem::file_separator ();
159    }
160
161  full_name += header_file;
162
163  deps.push_back (full_name);
164}
165
166
167//--------------------------------------------------
168static char* at_start_action (char* ptr,
169                              state_def& state,
170                              const cmt_string& dir_name,
171                              int current_path_index,
172                              const CmtSystem::cmt_string_vector& include_paths,
173                              const CmtSystem::cmt_string_vector& substitutions,
174                              const DepsBuilder::HeaderFilters& header_filters,
175                              CmtSystem::cmt_string_vector& all_deps,
176                              CmtSystem::cmt_string_vector& deps)
177{
178
179  char term = 0;
180  // To ignore leading spaces and tabs
181  while ( (*ptr == ' ') || (*ptr == '\t'))
182    {
183      ptr++;
184    }
185
186  if (*ptr == '#')
187    {
188      ptr++;
189
190      // skip spaces
191      while ((*ptr == ' ') || (*ptr == '\t')) ptr++;
192
193      if (!strncmp (ptr, "include", 7))
194        {
195          // We have a #include statement
196
197          ptr += 7;
198
199          while ((*ptr == ' ') || (*ptr == '\t')) ptr++;
200         
201          if (*ptr == '<')
202            {
203              term = '>';
204              ptr++;
205            }
206          else if (*ptr == '"')
207            {
208              term = '"';
209              ptr++;
210            }
211          else
212            {
213              // empty #include statement??
214              state = in_line;
215              ptr += strlen (ptr);
216              return (ptr);
217            }
218        }
219      else
220        {
221          // ignore other pre-processor statements
222
223          state = in_line;
224          ptr += strlen (ptr);
225          return (ptr);
226        }
227    }
228  else if (!strncmp (ptr, "      include", 13))
229    {
230      // fortran include statement
231
232      ptr += 13;
233
234      while ((*ptr == ' ') || (*ptr == '\t')) ptr++;
235
236      if (*ptr == '\'')
237        {
238          term = '\'';
239          ptr++;
240        }
241      else
242        {
243          state = in_line;
244          return (ptr);
245        }
246    }
247  else if (!strncmp (ptr, "\tinclude", 8))
248    {
249      // fortran include statement
250
251      ptr += 8;
252
253      while ((*ptr == ' ') || (*ptr == '\t')) ptr++;
254
255      if (*ptr == '\'')
256        {
257          term = '\'';
258          ptr++;
259        }
260      else
261        {
262          state = in_line;
263          return (ptr);
264        }
265    }
266  else
267    {
268      state = in_line;
269      return (ptr);
270    }
271
272  // At this point we do have to include a header file.
273
274  char* end;
275
276  end = strchr (ptr, term);
277  if (end != 0)
278    {
279      *end = 0;
280    }
281 
282  const char* header_file = ptr;
283 
284  header_file_action (header_file,
285                      dir_name,
286                      current_path_index,
287                      include_paths,
288                      substitutions,
289                      header_filters,
290                      all_deps,
291                      deps);
292 
293  if (end != 0)
294    {
295      *end = term;
296    }
297
298  state = in_line;
299  ptr += strlen (ptr);
300 
301  return (ptr);
302}
303
304/**
305   Any line with no header inclusion
306   step through comments and strings
307*/
308static char* in_line_action (char* ptr, state_def& state)
309{
310  char* pattern = ptr + strlen (ptr);
311  int length = 0;
312
313  /*
314    search for the first occurrence of
315    {single-quote double-quote open-comment open-line-comment}
316
317    Must exclude escaped quotes \' and \"
318  */
319
320  char* pos = strchr (ptr, '"');
321  if ((pos != 0) && (pos < pattern) && (pos > ptr) && (*(pos-1) != '\\'))
322    {
323      state = in_string;
324      pattern = pos;
325      length = 1;
326    }
327
328  pos = strchr (ptr, '\'');
329  if ((pos != 0) && (pos < pattern) && (pos > ptr) && (*(pos-1) != '\\'))
330    {
331      state = in_char;
332      pattern = pos;
333      length = 1;
334    }
335
336  pos = strstr (ptr, "/*");   //*/
337  if ((pos != 0) && (pos < pattern))
338    {
339      state = in_comment;
340      pattern = pos;
341      length = 2;
342    }
343
344  pos = strstr (ptr, "//");
345  if ((pos != 0) && (pos < pattern))
346    {
347      state = in_line_comment;
348      pattern = pos;
349      length = 2;
350    }
351
352  ptr = pattern + length;
353
354  return (ptr);
355}
356
357//--------------------------------------------------
358static char* in_string_action (char* ptr, state_def& state)
359{
360  // we exclusively look for a double quote
361
362  char* pos = strchr (ptr, '"');
363  if (pos == 0)
364    {
365      // This string is not finished till the end of the line..
366      // we expect it to continue to the next line...
367      // thus we leave the state as it is
368      ptr += strlen (ptr);
369    }
370  else
371    {
372      if ((pos > ptr) && (*(pos - 1) == '\\'))
373        {
374          ptr = pos + 1;
375        }
376      else
377        {
378          ptr = pos + 1;
379          state = in_line;
380        }
381    }
382
383  return (ptr);
384}
385
386//--------------------------------------------------
387static char* in_char_action (char* ptr, state_def& state)
388{
389  // we exclusively look for a single quote
390
391  char* pos = strchr (ptr, '\'');
392  if (pos == 0)
393    {
394      // This string is not finished till the end of the line..
395      // we expect it continues to the nex line...
396      // thus we leave the state as it is
397      ptr += strlen (ptr);
398    }
399  else
400    {
401      if ((pos > ptr) && (*(pos - 1) == '\\'))
402        {
403          ptr = pos + 1;
404        }
405      else
406        {
407          ptr = pos + 1;
408          state = in_line;
409        }
410    }
411
412  return (ptr);
413}
414
415//--------------------------------------------------
416static char* in_comment_action (char* ptr, state_def& state)
417{
418  char* pattern = ptr + strlen (ptr);
419  int length    = 0;
420  char* pos;
421 
422
423  /*
424    Even if we are inside a comment, we must detect strings since comment markers may
425    be written inside them.
426 
427    pos = strchr (ptr, '"');
428 
429    if ((pos != 0) && (pos < pattern) && (pos > ptr) && (*(pos-1) != '\\'))
430    {
431    state = in_string_comment;
432    pattern = pos;
433    length = 1;
434    }
435
436    pos = strchr (ptr, '\'');
437    if ((pos != 0) && (pos < pattern) && (pos > ptr) && (*(pos-1) != '\\'))
438    {
439    state = in_char_comment;
440    pattern = pos;
441    length = 1;
442    }
443  */
444  pos = strstr (ptr, "*/");
445  if ((pos != 0) && (pos < pattern))
446    {
447      state   = in_line;
448      pattern = pos;
449      length  = 2;
450    }
451
452  ptr = pattern + length;
453
454  return (ptr);
455}
456
457//--------------------------------------------------
458static char* in_string_comment_action (char* ptr, state_def& state)
459{
460  char* pos = strchr (ptr, '"');
461  if (pos == 0)
462    {
463      // This string is not finished till the end of the line..
464      // we expect it continues to the nex line...
465      ptr += strlen (ptr);
466    }
467  else
468    {
469      if ((pos > ptr) && (*(pos - 1) == '\\'))
470        {
471          ptr = pos + 1;
472        }
473      else
474        {
475          ptr = pos + 1;
476          state = in_comment;
477        }
478    }
479
480  return (ptr);
481}
482
483//--------------------------------------------------
484static char* in_char_comment_action (char* ptr, state_def& state)
485{
486  char* pos = strchr (ptr, '\'');
487  if (pos == 0)
488    {
489      // This string is not finished till the end of the line..
490      // we expect it continues to the nex line...
491      ptr += strlen (ptr);
492    }
493  else
494    {
495      if ((pos > ptr) && (*(pos - 1) == '\\'))
496        {
497          ptr = pos + 1;
498        }
499      else
500        {
501          ptr = pos + 1;
502          state = in_comment;
503        }
504      pos--;
505    }
506
507  return (ptr);
508}
509
510//--------------------------------------------------
511static char* in_line_comment_action (char* ptr, state_def& state)
512{
513  //  char * pos = strchr (ptr, '\\'); 
514  /* Extend this part to deal with continuation character */ 
515//   if ( (pos == NULL) || ( (ptr + strlen(ptr)-1)!=pos ))
516//     {
517//       state = in_line;
518//     }
519  /* We already deleted all backslash characters that with newline continue line */
520  state = in_line;
521  ptr    += strlen (ptr);
522 
523  return (ptr);
524}
525
526//--------------------------------------------------
527static void build_deps_text (char* text,
528                             const cmt_string& dir_name,
529                             int current_path_index,
530                             const CmtSystem::cmt_string_vector& include_paths,
531                             const CmtSystem::cmt_string_vector& substitutions,
532                             const DepsBuilder::HeaderFilters& header_filters,
533                             CmtSystem::cmt_string_vector& all_deps,
534                             CmtSystem::cmt_string_vector& deps)
535{
536  Log;
537
538  int line_number = 1;
539
540  log << "|build_deps_text> dir_name="
541      << dir_name << log_endl;
542
543  char* current = text;
544  char* nl;
545  int length;
546  char * ptr;
547  char * begin = current;
548 
549  state_def state = at_start;
550 
551  // nl -> new line
552  while (nl = strchr (begin, '\n'))
553    {
554      length = 0;
555
556      if (begin < nl)
557        {
558          if (*(nl - 1) == '\\')
559            {
560              // erase backslash + newline (continuation character)
561              // shift 2
562              begin = nl - 1;
563              char *d = begin;
564              char *s = nl + 1;
565              while (*d++ = *s++)
566                ;
567            }
568          else if (*(nl - 1) == '\r')
569            {
570              if ((begin < (nl - 1)) && (*(nl - 2) == '\\'))
571                {
572                  // erase backslash + carriage return + newline (continuation character)
573                  // shift 3
574                  begin = nl - 2;
575                  char *d = begin;
576                  char *s = nl + 1;
577                  while (*d++ = *s++)
578                    ;
579                }
580              else
581                {
582                  // process line [current, nl - 1)
583                  length = 2;
584                }
585            }
586          else
587            {
588              // process line [current, nl)
589              length = 1;
590            }
591        }
592      else
593        {
594          // process line [current, nl)
595          length = 1;
596        }
597     
598      if (0 == length) continue;
599
600      if (1 == length)
601        {
602          *nl = 0;
603        }
604      else
605        {
606          *(nl - 1) = 0;
607        }
608     
609      ptr = current;
610      log << "|build_deps_text> line=["
611          << current << "]" << log_endl;
612     
613      while (strlen (ptr) > 0)
614        {
615          switch (state)
616            {
617            case at_start:
618              ptr = at_start_action (ptr,
619                                     state,
620                                     dir_name,
621                                     current_path_index,
622                                     include_paths,
623                                     substitutions,
624                                     header_filters,
625                                     all_deps,
626                                     deps);
627              break;
628            case in_line:
629              ptr = in_line_action (ptr, state);
630              break;
631            case in_string:
632              ptr = in_string_action (ptr, state);
633              break;
634            case in_char:
635              ptr = in_char_action (ptr, state);
636              break;
637            case in_comment:
638              ptr = in_comment_action (ptr, state);
639              break;
640            case in_string_comment:
641              ptr = in_string_comment_action (ptr, state);
642              break;
643            case in_char_comment:
644              ptr = in_char_comment_action (ptr, state);
645              break;
646            case in_line_comment:
647              ptr = in_line_comment_action (ptr, state);
648              break;
649            }
650        } // while (strlen (ptr) > 0)
651     
652      if (state == in_line) state = at_start;
653      line_number++;
654
655      if (1 == length)
656        {
657          *nl = '\n';
658        }
659      else
660        {
661          *(nl - 1) = '\r';
662        }
663      current = nl + 1;
664      begin = current;
665
666    } // while (nl = ...)
667
668      ptr = current;
669      log << "|build_deps_text> line=["
670          << current << "]" << log_endl;
671     
672      while (strlen (ptr) > 0)
673        {
674          switch (state)
675            {
676            case at_start:
677              ptr = at_start_action (ptr,
678                                     state,
679                                     dir_name,
680                                     current_path_index,
681                                     include_paths,
682                                     substitutions,
683                                     header_filters,
684                                     all_deps,
685                                     deps);
686              break;
687            case in_line:
688              ptr = in_line_action (ptr, state);
689              break;
690            case in_string:
691              ptr = in_string_action (ptr, state);
692              break;
693            case in_char:
694              ptr = in_char_action (ptr, state);
695              break;
696            case in_comment:
697              ptr = in_comment_action (ptr, state);
698              break;
699            case in_string_comment:
700              ptr = in_string_comment_action (ptr, state);
701              break;
702            case in_char_comment:
703              ptr = in_char_comment_action (ptr, state);
704              break;
705            case in_line_comment:
706              ptr = in_line_comment_action (ptr, state);
707              break;
708            }
709        }
710 
711}
712
713//--------------------------------------------------
714static int build_deps (const cmt_string& name,
715                       const cmt_string& dir_name,
716                       int current_path_index,
717                       const CmtSystem::cmt_string_vector& include_paths,
718                       const CmtSystem::cmt_string_vector& substitutions,
719                       const DepsBuilder::HeaderFilters& header_filters,
720                       CmtSystem::cmt_string_vector& all_deps,
721                       CmtSystem::cmt_string_vector& deps)
722{
723  Log;
724
725  log << "CMT> build_deps name=" << name << " dir_name=" 
726      << dir_name << log_endl;
727
728  cmt_string full_name;
729  int path_index = locate (name,
730                           dir_name,
731                           include_paths,
732                           substitutions,
733                           full_name);
734
735  if (path_index >= 0)
736    {
737      cmt_string text;
738      if (!text.read (full_name))
739        {
740          CmtError::set (CmtError::file_access_error, full_name);
741          return -2;
742        }
743      char* ptr = &text[0];
744      cmt_string new_dir;
745      CmtSystem::dirname (full_name, new_dir);
746
747      if (path_index == 0 || path_index == 1)
748        build_deps_text (ptr, new_dir,
749                         current_path_index,
750                         include_paths, substitutions,
751                         header_filters,
752                         all_deps, deps);
753      else
754        build_deps_text (ptr, new_dir,
755                         path_index,
756                         include_paths, substitutions,
757                         header_filters,
758                         all_deps, deps);
759    }
760  if (path_index < 0)
761    {
762      log << "CMT> build_deps3" << log_endl;
763      CmtError::set (CmtError::path_not_found, name);
764    }
765  return path_index;
766}
767
768//--------------------------------------------------
769static int locate (const cmt_string& name,
770                   const cmt_string& dir_name,
771                   const CmtSystem::cmt_string_vector& include_paths,
772                   const CmtSystem::cmt_string_vector& substitutions,
773                   cmt_string& full_name)
774{
775  Log;
776
777  log << "CMT> locate name=" << name << " dir_name=" 
778      << dir_name << log_endl;
779
780  //
781  // Return 0 when the file is found in the current directory
782  //
783  if (CmtSystem::test_file (name))
784    {
785      full_name = name;
786      return (0);
787    }
788
789  cmt_string p;
790
791  //
792  // Return 1 when the file is found in the directory of the
793  // upper level source file
794  //
795  p = dir_name;
796  p += CmtSystem::file_separator ();
797  p += name;
798  if (CmtSystem::test_file (p))
799    {
800      full_name = p;
801      return (1);
802    }
803
804  //
805  // Return [path_index + 2] when the include file is found at one of
806  // the include_paths
807  //
808  for (int path_index = 0; path_index < include_paths.size (); path_index++)
809    {
810      p  = include_paths[path_index];
811      p += CmtSystem::file_separator ();
812      p += name;
813
814      log << "CMT> locate2 full_name=" << p << log_endl;
815
816      if (CmtSystem::test_file (p))
817        {
818          full_name = p;
819          return (path_index + 2);
820        }
821    }
822
823  log << "CMT> locate3" << log_endl;
824
825  return (-1);
826}
827
828//--------------------------------------------------------------------------
829DepsBuilder::DepsBuilder ()
830{ }
831
832//--------------------------------------------------------------------------
833DepsBuilder::~DepsBuilder ()
834{
835  clear ();
836}
837
838//--------------------------------------------------------------------------
839void DepsBuilder::clear ()
840{
841  m_include_paths.clear ();
842  m_substitutions.clear ();
843  for (int i = m_header_filters.size () - 1; i >= 0; i--)
844    {
845      m_header_filters[i].clear ();
846    }
847  m_header_filters.clear ();
848  m_deps.clear ();
849  m_all_deps.clear ();
850}
851
852//--------------------------------------------------------------------------
853void DepsBuilder::add (const cmt_string& path, const cmt_string& substitution)
854{
855  if (path.size () == 0)
856    {
857      return;
858    }
859
860  cmt_string p = path;
861  if (path[path.size () - 1] == CmtSystem::file_separator ())
862    {
863      p = path.substr(0, path.size () - 1);
864    }
865  for (int k = m_include_paths.size () - 1; k >= 0; k--)
866    if (m_include_paths[k] == p)
867      {
868        return;
869      }
870 
871  m_include_paths.push_back (p);
872  m_substitutions.push_back (substitution);
873}
874
875//--------------------------------------------------------------------------
876void DepsBuilder::add_includes (const Use& use)
877{
878  Log;
879
880  const Include::IncludeVector& includes = use.includes;
881  int include_number;
882
883  for (include_number = 0;
884       include_number < includes.size ();
885       include_number++)
886    {
887      const Include& include = includes[include_number];
888
889      cmt_string temp = include.name;
890      cmt_string pattern;
891      cmt_string name;
892      char end_pattern;
893
894      int start = 0;
895
896      for (;;)
897        {
898          int begin;
899
900          begin = temp.find (start, "${");
901          if (begin != cmt_string::npos)
902            {
903              end_pattern = '}';
904            }
905          else
906            {
907              begin = temp.find (start, "$(");
908              if (begin != cmt_string::npos)
909                {
910                  end_pattern = ')';
911                }
912              else
913                {
914                  break;
915                }
916            }
917
918          start = begin + 2;
919
920          int end;
921          end = temp.find (start, end_pattern);
922          if (end == cmt_string::npos) break;
923          if (end < begin) break;
924          start = end + 1;
925
926          temp.substr (begin, end - begin + 1, pattern);
927          temp.substr (begin + 2, end - begin - 2, name);
928
929          Symbol* macro = Symbol::find (name);
930          if (macro != 0)
931            {
932              cmt_string value = macro->resolve_macro_value ();
933              value += CmtSystem::file_separator ();
934              temp.replace_all (pattern, value);
935            }
936          else
937            {
938              cmt_string value = CmtSystem::getenv (name);
939              value += CmtSystem::file_separator ();
940              temp.replace_all (pattern, value);
941            }
942        }
943
944      log << "include = " << temp << log_endl;
945
946      add (temp, include.name);
947    }
948}
949
950//--------------------------------------------------------------------------
951CmtSystem::cmt_string_vector& DepsBuilder::run (const cmt_string& file_name,
952                                                const cmt_string& constituent_name)
953{
954  Log;
955
956  log << "Starting deps builder on " << file_name << log_endl;
957  CmtMessage::info ("calculating dependencies for " + file_name);
958
959  m_deps.clear ();
960  m_all_deps.clear ();
961
962  cmt_string preprocessor;
963  Symbol* macro = Symbol::find ("preprocessor_command");
964  if (macro != 0)
965    {
966      preprocessor = macro->resolve_macro_value ();
967    }
968
969  if (preprocessor == "")
970    {
971      //
972      //   Since no preprocessor command is defined,
973      // we use the internal mechanism provided here.
974      //
975      cmt_string new_dir;
976
977      CmtSystem::dirname (file_name, new_dir);
978
979      build_deps (file_name,
980                  new_dir,
981                  0,
982                  m_include_paths,
983                  m_substitutions,
984                  m_header_filters,
985                  m_all_deps,
986                  m_deps);
987    }
988  else
989    {
990      //
991      //  An external preprocessor command is defined. We expect it
992      // to follow a "standard" syntax for its output, ie:
993      //   o It starts with:
994      //       <module>.o: ...
995      //   o There may be many lines with trailing back-slashes
996      //   o All entries are space-separated
997      //   o One of the entries is the source file name itself
998      //
999      //  The preprocessor command expects the list of -I options
1000      // (resolved from the "includes" macro) and the list of
1001      // -D/-U options (resolved from the "*_pp_*flags" macros)
1002      //
1003
1004      //
1005      // Building the complete command (still the pp_*flags are
1006      // missing)
1007      //
1008      macro = Symbol::find ("includes");
1009      if (0 != macro)
1010        {
1011          preprocessor += " ";
1012          preprocessor += macro->resolve_macro_value ();
1013        }
1014      macro = Symbol::find ("app_" + constituent_name + "_cppflags");
1015      if (0 != macro)
1016        {
1017          preprocessor += " ";
1018          preprocessor += macro->resolve_macro_value ();
1019        }
1020      macro = Symbol::find ("lib_" + constituent_name + "_cppflags");
1021      if (0 != macro)
1022        {
1023          preprocessor += " ";
1024          preprocessor += macro->resolve_macro_value ();
1025        }
1026     
1027      preprocessor += " ";
1028      preprocessor += file_name;
1029     
1030      cmt_string output;
1031     
1032      int status = CmtSystem::execute (preprocessor, output);
1033      if (0 != status)
1034        {
1035          CmtError::set (CmtError::execution_failed, preprocessor, status);
1036          return m_deps;
1037        }
1038
1039      //
1040      // Make the output as one single big line.
1041      //
1042
1043      output.replace_all ("\n", " ");
1044      output.replace_all ("\\ ", " ");
1045     
1046      CmtSystem::cmt_string_vector files;
1047     
1048      CmtSystem::split (output, " \t", files);
1049
1050      //
1051      // Analyze each entry
1052      //
1053     
1054      for (int i = 1; i < files.size (); i++)
1055        {
1056          const cmt_string& file = files[i];
1057          if (file == file_name) continue;
1058         
1059          cmt_string dir;
1060          cmt_string name;
1061          cmt_string full_name;
1062         
1063          CmtSystem::dirname (file, dir);
1064
1065          //
1066          // Only declared include_paths will be taken into account
1067          // Others are considered as system include paths.
1068          //
1069         
1070          for (int j = 0; j < m_include_paths.size (); j++)
1071            {
1072              const cmt_string& p = m_include_paths[j];
1073              if (dir == p)
1074                {
1075                  CmtSystem::basename (file, name);
1076                  full_name = m_substitutions[j];
1077                  full_name += name;
1078
1079                  //
1080                  // We add in the "m_deps" list the symbolic form
1081                  // of the path rather that the expanded one.
1082                  //
1083                 
1084                  m_deps.push_back (full_name);
1085                 
1086                  break;
1087                }
1088            }
1089        }
1090    }
1091
1092  return (m_deps);
1093}
1094
1095//--------------------------------------------------------------------------
1096void DepsBuilder::add_header_filter (const Use* use, cmt_regexp* filter, const cmt_string& stamp)
1097{
1098  add_header_filter (HeaderFilter (use, filter, stamp));
1099}
1100
1101//--------------------------------------------------------------------------
1102void DepsBuilder::add_header_filter (const HeaderFilter& hf)
1103{
1104  m_header_filters.push_back (hf);
1105}
Note: See TracBrowser for help on using the repository browser.