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

Last change on this file since 580 was 427, checked in by rybkin, 17 years ago

See C.L. 333

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