source: CMT/v1r18p20041201/source/cmt_generator.cxx @ 1

Last change on this file since 1 was 1, checked in by arnault, 19 years ago

Import all tags

File size: 20.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 <errno.h>
8#include <stdio.h>
9
10#ifndef WIN32
11#include <unistd.h>
12#endif
13
14#include "cmt_generator.h"
15#include "cmt_use.h"
16#include "cmt_symbol.h"
17
18#include "cmt_generators.h"
19
20//------------------------------------------------------------------------
21void SourceFile::set (const cmt_string name, Language& language, const cmt_string output)
22{
23  m_name = name;
24  m_language = &language;
25  m_output = output;
26 
27  CmtSystem::reduce_file_separators (m_name);
28}
29
30cmt_string SourceFile::name () const
31{
32  return (m_name);
33}
34
35Language& SourceFile::language () const
36{
37  return (*m_language);
38}
39
40cmt_string SourceFile::output () const
41{
42  return (m_output);
43}
44//------------------------------------------------------------------------
45
46//--------------------------------------------------
47CmtGenerator::CmtGenerator ()
48{
49  m_CONSTITUENT.set ("CONSTITUENT");
50  m_LINKMACRO.set ("LINKMACRO");
51  m_DOCPATH.set ("DOCPATH");
52  m_PACKAGEPATH.set ("PACKAGEPATH");
53  m_PACKAGEPREFIX.set ("PACKAGEPREFIX");
54  m_PACKAGE.set ("PACKAGE");
55  m_VERSION.set ("VERSION");
56  m_MGRSTYLE.set ("MGRSTYLE");
57  m_TITLE.set ("TITLE");
58  m_GROUP.set ("GROUP");
59  m_CONSTITUENT.set ("CONSTITUENT");
60  m_CONSTITUENTSUFFIX.set ("CONSTITUENTSUFFIX");
61  m_LIBRARYSUFFIX.set ("LIBRARYSUFFIX");
62  m_USER.set ("USER");
63  m_DATE.set ("DATE");
64  m_PROTOTARGET.set ("PROTOTARGET");
65  m_OBJS.set ("OBJS");
66  m_CLASSES.set ("CLASSES");
67  m_PROTOSTAMPS.set ("PROTOSTAMPS");
68  m_NAME.set ("NAME");
69  m_FILEPATH.set ("FILEPATH");
70  m_FILESUFFIX.set ("FILESUFFIX");
71  m_SUFFIX.set ("SUFFIX");
72  m_FILENAME.set ("FILENAME");
73  m_LINKMACRO.set ("LINKMACRO");
74  m_LINE.set ("LINE");
75  m_ADDINCLUDE.set ("ADDINCLUDE");
76  m_FULLNAME.set ("FULLNAME");
77  m_DIRNAME.set ("DIRNAME");
78  m_OUTPUTNAME.set ("OUTPUTNAME");
79  m_ALLOS9SOURCES.set ("ALLOS9SOURCES");
80  m_NODEBUGUSELINKOPTS.set ("NODEBUGUSELINKOPTS");
81  m_DEBUGUSELINKOPTS.set ("DEBUGUSELINKOPTS");
82  m_USEINCLUDES.set ("USEINCLUDES");
83  m_HASTARGETTAG.set ("HASTARGETTAG");
84}
85
86//--------------------------------------------------
87void CmtGenerator::reset ()
88{
89  m_CONSTITUENT = "";
90  m_LINKMACRO = "";
91  m_DOCPATH = "";
92  m_PACKAGEPATH = "";
93  m_PACKAGEPREFIX = "";
94  m_PACKAGE = "";
95  m_VERSION = "";
96  m_MGRSTYLE = "";
97  m_TITLE = "";
98  m_GROUP = "";
99  m_CONSTITUENTSUFFIX = "";
100  m_LIBRARYSUFFIX = "";
101  m_USER = "";
102  m_DATE = "";
103  m_PROTOTARGET = "";
104  m_OBJS = "";
105  m_CLASSES = "";
106  m_PROTOSTAMPS = "";
107  m_NAME = "";
108  m_FILEPATH = "";
109  m_FILESUFFIX = "";
110  m_SUFFIX = "";
111  m_FILENAME = "";
112  m_LINE = "";
113  m_ADDINCLUDE = "";
114  m_FULLNAME = "";
115  m_OUTPUTNAME = "";
116  m_ALLOS9SOURCES = "";
117  m_NODEBUGUSELINKOPTS = "";
118  m_DEBUGUSELINKOPTS = "";
119  m_USEINCLUDES = "";
120  m_HASTARGETTAG = "";
121  m_PACKINCLUDES = "";
122  m_PACKOS9      = false;
123  m_GENERATOR    = "";
124
125  is_library     = false;
126  is_application = false;
127  srcdir       = "";
128  docdir       = "";
129  cmtdir       = "";
130  incdir       = "";
131  src          = "$(src)";
132  doc          = "$(doc)";
133  inc          = "$(inc)";
134  mgr          = "$(mgr)";
135  cmt          = "$(cmt)";
136  protos       = "";
137  protonames   = "";
138  os9sources   = "";
139
140  m_source_files.clear ();
141
142  Language::setup_all_fragments ();
143
144  CmtSystem::cd (Cmt::get_current_dir ());
145
146  cmt_string branch = CmtSystem::current_branch ();
147
148  if ((branch == "mgr") || (branch == "cmt"))
149    {
150      if (CmtSystem::test_directory ("../src"))
151        {
152          srcdir = "..";
153          srcdir += CmtSystem::file_separator ();
154          srcdir += "src";
155          srcdir += CmtSystem::file_separator ();
156        }
157      else
158        {
159          srcdir = "";
160        }
161
162      if (CmtSystem::test_directory ("../doc"))
163        {
164          docdir = "..";
165          docdir += CmtSystem::file_separator ();
166          docdir += "doc";
167          docdir += CmtSystem::file_separator ();
168        }
169      else
170        {
171          docdir = "";
172        }
173
174      if (CmtSystem::test_directory ("../cmt"))
175        {
176          cmtdir = "..";
177          cmtdir += CmtSystem::file_separator ();
178          cmtdir += "cmt";
179          cmtdir += CmtSystem::file_separator ();
180        }
181      else if (CmtSystem::test_directory ("../mgr"))
182        {
183          cmtdir = "..";
184          cmtdir += CmtSystem::file_separator ();
185          cmtdir += "mgr";
186          cmtdir += CmtSystem::file_separator ();
187        }
188      else
189        {
190          cmtdir = CmtSystem::pwd ();
191          cmtdir += CmtSystem::file_separator ();
192        }
193
194      if (CmtSystem::test_directory ("../src"))
195        {
196          incdir = "..";
197          incdir += CmtSystem::file_separator ();
198          incdir += "src";
199          incdir += CmtSystem::file_separator ();
200        }
201      else
202        {
203          incdir = "";
204        }
205    }
206  else
207    {
208      srcdir = ".";
209      srcdir += CmtSystem::file_separator ();
210      docdir = ".";
211      docdir += CmtSystem::file_separator ();
212      cmtdir = CmtSystem::pwd ();
213      cmtdir += CmtSystem::file_separator ();
214      incdir = ".";
215      incdir += CmtSystem::file_separator ();
216    }
217}
218
219//--------------------------------------------------
220bool CmtGenerator::prepare_output (const cmt_string& package,
221                                   const Constituent& constituent)
222{
223  m_PACKAGE = package;
224  m_CONSTITUENT = constituent.name;
225  m_CONSTITUENTSUFFIX = constituent.suffix;
226
227  m_PACKOS9 = constituent.need_OS9;
228
229  m_output_file_name = cmtdir + m_CONSTITUENT + ".";
230
231  if (Cmt::build_nmake ())
232    {
233      m_output_file_name += "nmake";
234    }
235  else
236    {
237      m_output_file_name += "make";
238    }
239 
240  m_output_file_name += "new";
241
242
243  m_output_file = fopen (m_output_file_name.c_str (), "wb");
244  if (m_output_file != NULL)
245    {
246      return (true);
247    }
248  else
249    {
250      return (false);
251    }
252}
253
254//--------------------------------------------------
255void CmtGenerator::check (const cmt_string& name)
256{
257  static cmt_string old;
258  static cmt_string backup;
259
260  old = name;
261
262  int pos = old.find_last_of ("new");
263  old.erase (pos);
264
265  if (!CmtSystem::compare_files (old, name))
266    {
267      backup = old;
268      backup += "sav";
269
270      unlink (backup.c_str ());
271      rename (old.c_str (), backup.c_str ());
272      rename (name.c_str (), old.c_str ());
273    }
274  else
275    {
276      unlink (name);
277    }
278}
279
280//--------------------------------------------------
281void CmtGenerator::commit (const cmt_string& name)
282{
283  static cmt_string old;
284  static cmt_string backup;
285
286  old = name;
287
288  int pos = old.find_last_of ("new");
289  old.erase (pos);
290
291  if (CmtSystem::test_file (old))
292    {
293      backup = old;
294      backup += "sav";
295
296      unlink (backup.c_str ());
297      rename (old.c_str (), backup.c_str ());
298    }
299
300  rename (name.c_str (), old.c_str ());
301}
302
303//--------------------------------------------------
304void CmtGenerator::terminate ()
305{
306  fclose (m_output_file);
307
308    //--- Complete the operation --------------
309
310  commit (m_output_file_name);
311}
312
313//--------------------------------------------------
314void CmtGenerator::fill_outputs ()
315{
316  bool first = true;
317
318  m_OBJS = "";
319
320  for (int i = 0; i < m_source_files.size (); i++)
321    {
322      const SourceFile& file = m_source_files[i];
323      const cmt_string output = file.output ();
324
325      if (output != "")
326        {
327          if (first)
328            {
329              first = false;
330            }
331          else
332            {
333              m_OBJS += " ";
334            }
335
336          m_OBJS += output;
337        }
338
339      if (Cmt::get_debug ())
340        {
341          cout << "CmtGenerator::fill_outputs> output=" << output << " OBJS=" << m_OBJS << endl;
342        }
343
344    }
345
346  if (Cmt::get_debug ())
347    {
348      cout << "CmtGenerator::fill_outputs> OBJS=" << m_OBJS << endl;
349    }
350
351}
352
353//--------------------------------------------------
354void CmtGenerator::prepare_use_context ()
355{
356  cmt_string path;
357  cmt_string substitution;
358
359  Use* use = &Use::current ();
360
361  m_deps_builder.clear ();
362
363  if (use->include_path != "none")
364    {
365      if (use->include_path == "")
366        {
367          m_deps_builder.add (incdir, "$(src)");
368        }
369      else
370        {
371          substitution = use->include_path;
372         
373          path = substitution;
374          Symbol::expand (path);
375         
376          CmtSystem::reduce_file_separators (path);
377
378          m_deps_builder.add (path, substitution);
379        }
380    }
381
382  m_deps_builder.add_includes (*use);
383
384  Use::UsePtrVector& uses = Use::get_ordered_uses ();
385
386  if (uses.size () > 0)
387    {
388      int number;
389
390      for (number = 0; number < uses.size (); number++)
391        {
392          use = uses[number];
393          if (use->discarded) continue;
394
395          if (use->real_path != "")
396            {
397              if (use->include_path != "none")
398                {
399                  if (use->include_path == "")
400                    {
401                      use->get_full_path (path);
402                      path += CmtSystem::file_separator ();
403                      path += "src";
404
405                      substitution = "$(";
406                      substitution += use->prefix;
407                      substitution += "ROOT)";
408                      substitution += CmtSystem::file_separator ();
409                      substitution += "src";
410                      substitution += CmtSystem::file_separator ();
411                    }
412                  else
413                    {
414                      substitution = use->include_path;
415
416                      path = substitution;
417                      Symbol::expand (path);
418
419                      CmtSystem::reduce_file_separators (path);
420                    }
421
422                  m_deps_builder.add (path, substitution);
423                }
424
425              m_deps_builder.add_includes (*use);
426            }
427        }
428    }
429}
430
431//--------------------------------------------------
432void CmtGenerator::filter_path (cmt_string& text)
433{
434  CmtSystem::compress_path (text);
435
436  text.replace_all ("./../src/../", "../");
437  text.replace_all ("./../src/", "$(src)");
438
439  text.replace_all (".\\..\\src\\..\\", "..\\");
440  text.replace_all (".\\..\\src\\", "$(src)");
441
442  text.replace_all ("../src/../", "../");
443  text.replace_all ("../src/", "$(src)");
444
445  text.replace_all ("..\\src\\..\\", "..\\");
446  text.replace_all ("..\\src\\", "$(src)");
447
448  text.replace_all ("../doc/../", "../");
449  text.replace_all ("../doc/", "$(doc)");
450
451  text.replace_all ("..\\doc\\..\\", "..\\");
452  text.replace_all ("..\\doc\\", "$(doc)");
453
454  text.replace_all ("$(src)$(src)", "$(src)");
455}
456
457/**
458   Scan a complete file spec (with possibly wild cards and directory)
459   given in full_name ad fill in a vector of found file names.
460
461   Result of the scan is filtered against matching suffixes
462
463   Returns the count of non empty file names really found.
464
465*/
466int CmtGenerator::get_all_files (const cmt_string& full_name,
467                                 const cmt_vector<cmt_regexp>& exclude_exprs,
468                                 const cmt_vector<cmt_regexp>& select_exprs,
469                                 CmtSystem::cmt_string_vector& files)
470{
471  static cmt_string suffix;
472  static cmt_string name;
473
474  bool has_excludes = false;
475  bool has_selects = false;
476
477  suffix = "";
478  name = "";
479
480  files.clear ();
481
482  has_excludes = (exclude_exprs.size () > 0);
483  has_selects = (select_exprs.size () > 0);
484
485  CmtSystem::get_dot_suffix (full_name, suffix);
486
487  bool wilcarded_suffix = false;
488
489  if (suffix == ".*") wilcarded_suffix = true;
490
491  int count = 0;
492
493  if (full_name.find ('*') != cmt_string::npos)
494    {
495      CmtSystem::scan_dir (full_name, files);
496
497      if (Cmt::get_debug ())
498        {
499          cout << "CMT::get_all_files> full_name=" << full_name <<
500            " pwd=" << CmtSystem::pwd () << endl;
501          cout << "CMT::get_all_files> files.size=" <<  files.size () << endl;
502        }
503
504        /**
505
506           We have to treat patterns of the form *.xxx (ie with a
507           suffix) thus we filter out everything that could have been
508           collected with a different suffix because the
509           CmtSystem::scan_dir function only handles patterns of the
510           form xxx* (ie with trailing *)
511
512           [If the original suffix was empty (ie files specified using
513           xx*) this means getting files without any dot-suffix. This
514           may be incorrect??]
515
516        */
517
518      for (int j = 0; j < files.size (); j++)
519        {
520          cmt_string& n = files[j];
521
522          bool rejected = false;
523
524          if (n == "")
525            {
526              rejected = true;
527            }
528
529          if (!rejected && has_selects)
530            {
531              rejected = true;
532
533              for (int k = 0; k < select_exprs.size (); k++)
534                {
535                  const cmt_regexp& exp = select_exprs[k];
536                  if (exp.match (n))
537                    {
538                      rejected = false;
539                      break;
540                    }
541                }
542            }
543
544          if (!rejected && has_excludes)
545            {
546              for (int k = 0; k < exclude_exprs.size (); k++)
547                {
548                  const cmt_regexp& exp = exclude_exprs[k];
549                  if (exp.match (n))
550                    {
551                      rejected = true;
552                      break;
553                    }
554                }
555            }
556
557          if (!rejected)
558            {
559              static cmt_string s;
560
561              CmtSystem::get_dot_suffix (n, s);
562              if (!wilcarded_suffix && (s != suffix)) 
563                {
564                  rejected = true;
565                }
566              else
567                {
568                  count++;
569                }
570            }
571
572          if (Cmt::get_debug ())
573            {
574              if (rejected)
575                {
576                  cout << "CMT::get_all_files> reject " <<  n << endl;
577                }
578              else
579                {
580                  cout << "CMT::get_all_files> keep " <<  n << endl;
581                }
582            }
583
584          if (rejected)
585            {
586              n = "";
587            }
588        }
589    }
590  else
591    {
592      if (full_name != "")
593        {
594          bool rejected = false;
595
596          if (has_excludes)
597            {
598              for (int k = 0; k < exclude_exprs.size (); k++)
599                {
600                  const cmt_regexp& exp = exclude_exprs[k];
601                  if (exp.match (full_name))
602                    {
603                      rejected = true;
604                      break;
605                    }
606                }
607            }
608
609          if (!rejected)
610            {
611              cmt_string& n = files.add ();
612
613              n = full_name;
614
615              count++;
616            }
617        }
618    }
619
620  return (count);
621}
622
623//--------------------------------------------------
624void CmtGenerator::set_full_name (cmt_string& full_name, cmt_string& file)
625{
626  full_name = "";
627
628  Symbol::expand (file);
629
630  if (file == "") return;
631 
632  if (!CmtSystem::absolute_path (file))
633    {
634      full_name = srcdir;
635      if (full_name != "") full_name += CmtSystem::file_separator ();
636    }
637 
638  full_name += file;
639
640  CmtSystem::reduce_file_separators (full_name);
641}
642
643//------------------------------------------------------------------------
644static ApplicationGenerator ApplicationContext;
645static LibraryGenerator LibraryContext;
646static DocumentGenerator DocumentContext;
647static ReadmeGenerator ReadmeContext;
648static PrototypeGenerator PrototypeContext;
649static DefaultMakefileGenerator DefaultMakefileContext;
650static MSDEVGenerator MSDEVContext;
651static VSNETGenerator VSNETContext;
652static MakeSetupGenerator MakeSetupContext;
653static ConstituentsMakefileGenerator ConstituentsMakefileContext;
654static DependencyGenerator DependencyContext;
655
656//--------------------------------------------------
657int Generator::build_msdev_workspace (const Constituent::ConstituentVector& constituents)
658{
659  return (MSDEVContext.build_workspace (constituents));
660}
661
662//--------------------------------------------------
663int Generator::build_msdev (const Constituent& constituent)
664{
665  return (MSDEVContext.build_project (constituent));
666}
667
668//--------------------------------------------------
669int Generator::build_vsnet_workspace (const Constituent::ConstituentVector& constituents)
670{
671  return (VSNETContext.build_workspace (constituents));
672}
673
674//--------------------------------------------------   
675int Generator::build_vsnet (const Constituent& constituent)
676{
677  return (VSNETContext.build_project (constituent));
678}
679
680//--------------------------------------------------
681void Generator::build_make_setup (const cmt_string& package)
682{
683  MakeSetupContext.build (package);
684}
685
686//--------------------------------------------------
687void Generator::build_constituents_makefile (const cmt_string& package,
688                                             const CmtSystem::cmt_string_vector& arguments)
689{
690  ConstituentsMakefileContext.build (package, arguments);
691}
692
693//--------------------------------------------------
694int Generator::build_constituent_makefile (const Constituent& constituent)
695{
696  const cmt_string& package = Cmt::get_current_package ();
697
698  switch (constituent.type)
699    {
700    case Application:
701      ApplicationContext.build (package, constituent);
702      break;
703    case Library:
704      LibraryContext.build (package, constituent);
705      break;
706    case Document:
707      DocumentContext.build (package, constituent);
708      break;
709    }
710
711  return (0);
712}
713
714//--------------------------------------------------
715void Generator::build_constituent_makefile (const cmt_string& name)
716{
717  const Constituent* constituent = Constituent::find (name);
718  if (constituent != 0) build_constituent_makefile (*constituent);
719}
720
721//--------------------------------------------------
722void Generator::build_default_makefile ()
723{
724  DefaultMakefileContext.build ();
725}
726
727//--------------------------------------------------
728void Generator::build_dependencies (const CmtSystem::cmt_string_vector& arguments)
729{
730  DependencyContext.build (arguments);
731}
732
733//--------------------------------------------------
734void Generator::build_prototype (const cmt_string& file_name)
735{
736  PrototypeContext.build (file_name);
737}
738
739//--------------------------------------------------
740void Generator::build_readme (const CmtSystem::cmt_string_vector& arguments)
741{
742  ReadmeContext.build (arguments);
743}
744
745class WinDefAwk : public PAwk
746{
747public :
748   WinDefAwk (const cmt_string& library_name)
749    {
750      m_name = library_name;
751    }
752
753  void begin ()
754    {
755      cout << "LIBRARY " << m_name << endl;
756      cout << "EXPORTS" << endl;
757    }
758
759  void filter (const cmt_string& line)
760    {
761      if (line.find ("External") == cmt_string::npos) return;
762      if (line.find ("??_") != cmt_string::npos)
763        {
764          if (line.find ("operator/=") == cmt_string::npos) return;
765          // Keep operator /= .
766        }
767
768      CmtSystem::cmt_string_vector words;
769      CmtSystem::split (line, " \t", words);
770      if (words.size () >= 8)
771        {
772          int pos = 7;
773
774          cmt_string& fifth_word = words[4];
775          if (fifth_word == "()") pos = 7;
776          else if (fifth_word == "External") pos = 6;
777          else return;
778
779          cmt_string& symbol = words[pos];
780          if (symbol[0] == '_') symbol.erase (0, 1);
781          symbol.replace_all ("\r", "");
782          symbol.replace_all ("\n", "");
783
784          if ((pos == 6) && (line.find("static class") != cmt_string::npos))
785            {
786              // static class objects are not DATA :
787              cout << " " << symbol << " " << endl;
788            } 
789          else if (pos == 6)
790            {
791              // DATA :
792              cout << " " << symbol << "\tDATA" << endl;
793            } 
794          else
795            {
796              // code :
797              cout << " " << symbol << " " << endl;
798            } 
799        }
800    }
801
802  void end ()
803    {
804    }
805
806private:
807  cmt_string m_name;
808};
809
810//--------------------------------------------------
811void Generator::build_windefs (const cmt_string& library_name)
812{
813  cmt_string bin;
814  cmt_string name;
815  cmt_string suffix;
816
817  CmtSystem::dirname (library_name, bin);
818  CmtSystem::get_dot_suffix (library_name, suffix);
819  CmtSystem::basename (library_name, suffix, name);
820 
821  if (!CmtSystem::cd (bin)) return;
822 
823  cmt_string text;
824  cmt_string command;
825 
826  command = "dumpbin /symbols ";
827  command += library_name;
828       
829  WinDefAwk filter (name);
830 
831  filter.run (command, "SECT");
832}
833
834//--------------------------------------------------
835void Packager::begin ()
836{
837  m_package_name = "";
838}
839
840void Packager::filter (const cmt_string& line)
841{
842  CmtSystem::cmt_string_vector words;
843
844  CmtSystem::split (line, " ", words);
845  if (words.size () > 1)
846    {
847      cmt_string& w = words[0];
848
849      if (w == "package")
850        {
851          m_package_name = words[1];
852
853          int pos = m_package_name.find (";");
854          if (pos != cmt_string::npos) m_package_name.erase (pos);
855          m_package_name.replace_all (".", CmtSystem::file_separator ());
856        }
857    }
858}
859
860cmt_string& Packager::package_name ()
861{
862  return (m_package_name);
863}
864
Note: See TracBrowser for help on using the repository browser.