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