source: CMT/v1r18p20050401/source/cmt_syntax.cxx @ 594

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

Accept HEAD as a valid version directory - CL261

  • Property svn:eol-style set to native
File size: 30.7 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_syntax.h"
8#include "cmt.h"
9#include "cmt_symbol.h"
10#include "cmt_constituent.h"
11#include "cmt_pattern.h"
12#include "cmt_error.h"
13#include "cmt_branch.h"
14#include "cmt_error.h"
15#include "cmt_script.h"
16#include "cmt_language.h"
17#include "cmt_project.h"
18#include "cmt_cmtpath_pattern.h"
19
20void Kwd::action (const CmtSystem::cmt_string_vector& words,
21                  Project* project,
22                  const cmt_string& file_name,
23                  int line_number)
24{
25}
26
27class KwdAction : public Kwd
28{
29public:
30  void action (const CmtSystem::cmt_string_vector& words,
31               Use* use,
32               const cmt_string& file_name,
33               int line_number)
34  {
35    Symbol::action (words, CommandAction, use);
36  }
37};
38
39class KwdAlias : public Kwd
40{
41public:
42  void action (const CmtSystem::cmt_string_vector& words,
43               Use* use,
44               const cmt_string& file_name,
45               int line_number)
46  {
47    Symbol::action (words, CommandAlias, use);
48  }
49};
50
51class KwdApplication : public Kwd
52{
53public:
54  void action (const CmtSystem::cmt_string_vector& words,
55               Use* use,
56               const cmt_string& file_name,
57               int line_number)
58  {
59    if (use == &(Use::current ()))
60      {
61        Constituent::action (Application, words);
62      }
63  }
64};
65
66class KwdApplyPattern : public Kwd
67{
68public:
69  void action (const CmtSystem::cmt_string_vector& words,
70               Use* use,
71               const cmt_string& file_name,
72               int line_number)
73  {
74    ApplyPattern::action (words, use);
75  }
76};
77
78class KwdApplyTag : public Kwd
79{
80public:
81  void action (const CmtSystem::cmt_string_vector& words,
82               Use* use,
83               const cmt_string& file_name,
84               int line_number)
85  {
86    Tag::action_apply (words, use);
87  }
88};
89
90class KwdAuthor : public Kwd
91{
92public:
93  void action (const CmtSystem::cmt_string_vector& words,
94               Use* use,
95               const cmt_string& file_name,
96               int line_number)
97  {
98    use->author_action (words);
99  }
100};
101
102class KwdBranches : public Kwd
103{
104public:
105  void action (const CmtSystem::cmt_string_vector& words,
106               Use* use,
107               const cmt_string& file_name,
108               int line_number)
109  {
110    if (use == &(Use::current ())) 
111      {
112        Branch::action (words);
113      }
114  }
115};
116
117class KwdBuildStrategy : public Kwd
118{
119public:
120  bool decode (const cmt_string& w, cmt_string& strategy, cmt_string& value)
121  {
122    bool result = true;
123
124    value = w;
125
126    if (w == "prototypes")
127      {
128        strategy = "BuildPrototypes";
129      }
130    else if (w == "no_prototypes")
131      {
132        strategy = "BuildPrototypes";
133      }
134    else if ((w == "with_installarea") || (w == "with_install_area"))
135      {
136        value = "with_installarea";
137        strategy = "InstallArea";
138      }
139    else if ((w == "without_installarea") || (w == "without_install_area"))
140      {
141        value = "without_installarea";
142        strategy = "InstallArea";
143      }
144    else
145      {
146        result = false;
147      }
148
149    return (result);
150  }
151
152  void action (const CmtSystem::cmt_string_vector& words,
153               Use* use,
154               const cmt_string& file_name,
155               int line_number)
156  {
157    cmt_string cmtpath;
158    cmt_string offset;
159
160    use->get_cmtpath_and_offset (cmtpath, offset);
161
162    Project* p = Project::find_by_cmtpath (cmtpath);
163
164    for (int i = 1; i < words.size (); i++)
165      {
166        const cmt_string& w = words[i];
167
168        cmt_string strategy;
169        cmt_string value;
170
171        bool in_error = false;
172
173        if (decode (w, strategy, value))
174          {
175            if (p != 0) p->set_strategy (strategy, value, use->get_package_name ());
176          }
177        else
178          {
179            in_error = true;
180
181            CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword");
182          }
183      }
184  }
185
186  void action (const CmtSystem::cmt_string_vector& words,
187               Project* project,
188               const cmt_string& file_name,
189               int line_number)
190  {
191    for (int i = 1; i < words.size (); i++)
192      {
193        const cmt_string& w = words[i];
194
195        cmt_string strategy;
196        cmt_string value;
197
198        bool in_error = false;
199
200        if (decode (w, strategy, value))
201          {
202            if (project != 0) project->set_strategy (strategy, value, "");
203          }
204        else
205          {
206            in_error = true;
207
208            CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword");
209          }
210      }
211  }
212};
213
214class KwdCleanupScript : public Kwd
215{
216public:
217  void action (const CmtSystem::cmt_string_vector& words,
218               Use* use,
219               const cmt_string& file_name,
220               int line_number)
221  {
222    Script::action (words, CleanupScript, use);
223    Symbol::action (words, CommandCleanupScript, use);
224  }
225};
226
227class KwdCmtPathPattern : public Kwd
228{
229public:
230  void action (const CmtSystem::cmt_string_vector& words,
231               Use* use,
232               const cmt_string& /*file_name*/,
233               int /*line_number*/)
234  {
235    CmtPathPattern::action (words, use);
236  }
237};
238
239class KwdDocument : public Kwd
240{
241public:
242  void action (const CmtSystem::cmt_string_vector& words,
243               Use* use,
244               const cmt_string& file_name,
245               int line_number)
246  {
247    if (use == &(Use::current ()))
248      {
249        Constituent::action (Document, words);
250      }
251  }
252};
253
254class KwdEndPrivate : public Kwd
255{
256public:
257  void action (const CmtSystem::cmt_string_vector& words,
258               Use* use,
259               const cmt_string& file_name,
260               int line_number)
261  {
262    if (use != &(Use::current ()))
263      {
264        use->pop_scope_section ();
265      }
266  }
267};
268
269class KwdEndPublic : public Kwd
270{
271public:
272  void action (const CmtSystem::cmt_string_vector& words,
273               Use* use,
274               const cmt_string& file_name,
275               int line_number)
276  {
277    if (use != &(Use::current ()))
278      {
279        use->pop_scope_section ();
280      }
281  }
282};
283
284class KwdIgnorePattern : public Kwd
285{
286public:
287  void action (const CmtSystem::cmt_string_vector& words,
288               Use* use,
289               const cmt_string& file_name,
290               int line_number)
291  {
292    IgnorePattern::action (words, use);
293  }
294};
295
296class KwdIncludeDirs : public Kwd
297{
298public:
299  void action (const CmtSystem::cmt_string_vector& words,
300               Use* use,
301               const cmt_string& file_name,
302               int line_number)
303  {
304    Include::action (words, use);
305  }
306};
307
308class KwdIncludePath : public Kwd
309{
310public:
311  void action (const CmtSystem::cmt_string_vector& words,
312               Use* use,
313               const cmt_string& file_name,
314               int line_number)
315  {
316    if (words.size () > 1)
317      {
318        use->set_include_path (words[1]);
319      }
320  }
321};
322
323class KwdLanguage : public Kwd
324{
325public:
326  void action (const CmtSystem::cmt_string_vector& words,
327               Use* use,
328               const cmt_string& file_name,
329               int line_number)
330  {
331    Language::action (words);
332  }
333};
334
335class KwdLibrary : public Kwd
336{
337public:
338  void action (const CmtSystem::cmt_string_vector& words,
339               Use* use,
340               const cmt_string& file_name,
341               int line_number)
342  {
343    if (use == &(Use::current ()))
344      {
345        Constituent::action (Library, words);
346      }
347  }
348};
349
350class KwdMacro : public Kwd
351{
352public:
353  void action (const CmtSystem::cmt_string_vector& words,
354               Use* use,
355               const cmt_string& file_name,
356               int line_number)
357  {
358    Symbol::action (words, CommandMacro, use);
359  }
360};
361
362class KwdMacroPrepend : public Kwd
363{
364public:
365  void action (const CmtSystem::cmt_string_vector& words,
366               Use* use,
367               const cmt_string& file_name,
368               int line_number)
369  {
370    Symbol::action (words, CommandMacroPrepend, use);
371  }
372};
373
374class KwdMacroAppend : public Kwd
375{
376public:
377  void action (const CmtSystem::cmt_string_vector& words,
378               Use* use,
379               const cmt_string& file_name,
380               int line_number)
381  {
382    Symbol::action (words, CommandMacroAppend, use);
383  }
384};
385
386class KwdMacroRemove : public Kwd
387{
388public:
389  void action (const CmtSystem::cmt_string_vector& words,
390               Use* use,
391               const cmt_string& file_name,
392               int line_number)
393  {
394    Symbol::action (words, CommandMacroRemove, use);
395  }
396};
397
398class KwdMacroRemoveRegexp : public Kwd
399{
400public:
401  void action (const CmtSystem::cmt_string_vector& words,
402               Use* use,
403               const cmt_string& file_name,
404               int line_number)
405  {
406    Symbol::action (words, CommandMacroRemoveRegexp, use);
407  }
408};
409
410class KwdMacroRemoveAll : public Kwd
411{
412public:
413  void action (const CmtSystem::cmt_string_vector& words,
414               Use* use,
415               const cmt_string& file_name,
416               int line_number)
417  {
418    Symbol::action (words, CommandMacroRemoveAll, use);
419  }
420};
421
422class KwdMacroRemoveAllRegexp : public Kwd
423{
424public:
425  void action (const CmtSystem::cmt_string_vector& words,
426               Use* use,
427               const cmt_string& file_name,
428               int line_number)
429  {
430    Symbol::action (words, CommandMacroRemoveAllRegexp, use);
431  }
432};
433
434class KwdMakeFragment : public Kwd
435{
436public:
437  void action (const CmtSystem::cmt_string_vector& words,
438               Use* use,
439               const cmt_string& file_name,
440               int line_number)
441  {
442    Fragment::action (words, use);
443  }
444};
445
446class KwdManager : public Kwd
447{
448public:
449  void action (const CmtSystem::cmt_string_vector& words,
450               Use* use,
451               const cmt_string& file_name,
452               int line_number)
453  {
454    use->manager_action (words);
455  }
456};
457
458class KwdPackage : public Kwd
459{
460public:
461  void action (const CmtSystem::cmt_string_vector& words,
462               Use* use,
463               const cmt_string& file_name,
464               int line_number)
465  {
466    /*
467    if (words.size () > 1)
468      {
469        if (use == &(Use::current()))
470          {
471            m_current_package = words[1];
472            build_prefix (m_current_package, m_current_prefix);
473           
474            if ((use->get_package_name () != "") &&
475                (use->get_package_name () != m_current_package))
476              {
477                if (!m_quiet)
478                  {
479                    //  cerr << "#CMT> package name mismatch in requirements of " <<
480                    //  use->get_package_name () << " " <<
481                    //  use->version << " line #" << line_number;
482                    //  cerr << " : " << m_current_package << " versus " <<
483                    //  use->get_package_name () << endl;
484                  }
485              }
486           
487            use->set (m_current_package,
488                      m_current_version,
489                      m_current_path,
490                      "",
491                      "");
492           
493            use->change_path (m_current_path);
494            use->style = m_current_style;
495          }
496      }
497    */
498  }
499};
500
501class KwdPath : public Kwd
502{
503public:
504  void action (const CmtSystem::cmt_string_vector& words,
505               Use* use,
506               const cmt_string& file_name,
507               int line_number)
508  {
509    Symbol::action (words, CommandPath, use);
510  }
511};
512
513class KwdPathAppend : public Kwd
514{
515public:
516  void action (const CmtSystem::cmt_string_vector& words,
517               Use* use,
518               const cmt_string& file_name,
519               int line_number)
520  {
521    Symbol::action (words, CommandPathAppend, use);
522  }
523};
524
525class KwdPathPrepend : public Kwd
526{
527public:
528  void action (const CmtSystem::cmt_string_vector& words,
529               Use* use,
530               const cmt_string& file_name,
531               int line_number)
532  {
533    Symbol::action (words, CommandPathPrepend, use);
534  }
535};
536
537class KwdPathRemove : public Kwd
538{
539public:
540  void action (const CmtSystem::cmt_string_vector& words,
541               Use* use,
542               const cmt_string& file_name,
543               int line_number)
544  {
545    Symbol::action (words, CommandPathRemove, use);
546  }
547};
548
549class KwdPathRemoveRegexp : public Kwd
550{
551public:
552  void action (const CmtSystem::cmt_string_vector& words,
553               Use* use,
554               const cmt_string& file_name,
555               int line_number)
556  {
557    Symbol::action (words, CommandPathRemoveRegexp, use);
558  }
559};
560
561class KwdPattern : public Kwd
562{
563public:
564  void action (const CmtSystem::cmt_string_vector& words,
565               Use* use,
566               const cmt_string& file_name,
567               int line_number)
568  {
569    Pattern::action (words, use);
570  }
571};
572
573class KwdPrivate : public Kwd
574{
575public:
576  void action (const CmtSystem::cmt_string_vector& words,
577               Use* use,
578               const cmt_string& file_name,
579               int line_number)
580  {
581    if (use != &(Use::current ()))
582      {
583        use->push_scope_section (ScopePrivate);
584      }
585  }
586};
587
588class KwdProject : public Kwd
589{
590public:
591  void action (const CmtSystem::cmt_string_vector& words,
592               Use* use,
593               const cmt_string& file_name,
594               int line_number)
595  {
596  }
597
598  void action (const CmtSystem::cmt_string_vector& words,
599               Project* project,
600               const cmt_string& file_name,
601               int line_number)
602  {
603  }
604};
605
606class KwdPublic : public Kwd
607{
608public:
609  void action (const CmtSystem::cmt_string_vector& words,
610               Use* use,
611               const cmt_string& file_name,
612               int line_number)
613  {
614    if (use != &(Use::current ()))
615      {
616        use->push_scope_section (ScopePublic);
617      }
618  }
619};
620
621class KwdSet : public Kwd
622{
623public:
624  void action (const CmtSystem::cmt_string_vector& words,
625               Use* use,
626               const cmt_string& file_name,
627               int line_number)
628  {
629    Symbol::action (words, CommandSet, use);
630  }
631};
632
633class KwdSetAppend : public Kwd
634{
635public:
636  void action (const CmtSystem::cmt_string_vector& words,
637               Use* use,
638               const cmt_string& file_name,
639               int line_number)
640  {
641    Symbol::action (words, CommandSetAppend, use);
642  }
643};
644
645class KwdSetPrepend : public Kwd
646{
647public:
648  void action (const CmtSystem::cmt_string_vector& words,
649               Use* use,
650               const cmt_string& file_name,
651               int line_number)
652  {
653    Symbol::action (words, CommandSetPrepend, use);
654  }
655};
656
657class KwdSetRemove : public Kwd
658{
659public:
660  void action (const CmtSystem::cmt_string_vector& words,
661               Use* use,
662               const cmt_string& file_name,
663               int line_number)
664  {
665    Symbol::action (words, CommandSetRemove, use);
666  }
667};
668
669class KwdSetRemoveRegexp : public Kwd
670{
671public:
672  void action (const CmtSystem::cmt_string_vector& words,
673               Use* use,
674               const cmt_string& file_name,
675               int line_number)
676  {
677    Symbol::action (words, CommandSetRemoveRegexp, use);
678  }
679};
680
681class KwdSetupScript : public Kwd
682{
683public:
684  void action (const CmtSystem::cmt_string_vector& words,
685               Use* use,
686               const cmt_string& file_name,
687               int line_number)
688  {
689    Script::action (words, SetupScript, use);
690    Symbol::action (words, CommandSetupScript, use);
691  }
692};
693
694class KwdSetupStrategy : public Kwd
695{
696public:
697  bool decode (const cmt_string& w, cmt_string& strategy, cmt_string& value)
698  {
699    bool result = true;
700
701    value = w;
702
703    if (w == "config")
704      {
705        strategy = "SetupConfig";
706      }
707    else if (w == "no_config")
708      {
709        strategy = "SetupConfig";
710      }
711    else if (w == "root")
712      {
713        strategy = "SetupRoot";
714      }
715    else if (w == "no_root")
716      {
717        strategy = "SetupRoot";
718      }
719    else if (w == "cleanup")
720      {
721        strategy = "SetupCleanup";
722      }
723    else if (w == "no_cleanup")
724      {
725        strategy = "SetupCleanup";
726      }
727    else
728      {
729        result = false;
730      }
731
732    return (result);
733  }
734
735  void action (const CmtSystem::cmt_string_vector& words,
736               Use* use,
737               const cmt_string& file_name,
738               int line_number)
739  {
740    cmt_string cmtpath;
741    cmt_string offset;
742
743    use->get_cmtpath_and_offset (cmtpath, offset);
744
745    Project* p = Project::find_by_cmtpath (cmtpath);
746
747    for (int i = 1; i < words.size (); i++)
748      {
749        const cmt_string& w = words[i];
750
751        cmt_string strategy;
752        cmt_string value;
753
754        bool in_error = false;
755
756        if (decode (w, strategy, value))
757          {
758            if (p != 0) p->set_strategy (strategy, value, use->get_package_name ());
759          }
760        else
761          {
762            in_error = true;
763
764            CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword");
765          }
766      }
767  }
768
769  void action (const CmtSystem::cmt_string_vector& words,
770               Project* project,
771               const cmt_string& file_name,
772               int line_number)
773  {
774    for (int i = 1; i < words.size (); i++)
775      {
776        const cmt_string& w = words[i];
777
778        cmt_string strategy;
779        cmt_string value;
780
781        bool in_error = false;
782
783        if (decode (w, strategy, value))
784          {
785            if (project != 0) project->set_strategy (strategy, value, "");
786          }
787        else
788          {
789            in_error = true;
790
791            CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword");
792          }
793      }
794  }
795};
796
797class KwdTag : public Kwd
798{
799public:
800  void action (const CmtSystem::cmt_string_vector& words,
801               Use* use,
802               const cmt_string& file_name,
803               int line_number)
804  {
805    Tag::action (words, use);
806  }
807};
808
809class KwdTagExclude : public Kwd
810{
811public:
812  void action (const CmtSystem::cmt_string_vector& words,
813               Use* use,
814               const cmt_string& file_name,
815               int line_number)
816  {
817    Tag::action_exclude (words, use);
818  }
819};
820
821class KwdUse : public Kwd
822{
823public:
824  void action (const CmtSystem::cmt_string_vector& words,
825               Use* use,
826               const cmt_string& file_name,
827               int line_number)
828  {
829    Use::action (words, use);
830  }
831
832  void action (const CmtSystem::cmt_string_vector& words,
833               Project* project,
834               const cmt_string& file_name,
835               int line_number)
836  {
837    project->use_action (words[1], words[2]);
838  }
839};
840
841class KwdVersionStrategy : public Kwd
842{
843public:
844  void action (const CmtSystem::cmt_string_vector& words,
845               Use* use,
846               const cmt_string& file_name,
847               int line_number)
848  {
849    cerr << "# Package " << use->get_package_name () <<
850      " sets obsolescent version strategy" << endl;
851  }
852};
853
854class KwdVersion : public Kwd
855{
856public:
857  void action (const CmtSystem::cmt_string_vector& words,
858               Use* use,
859               const cmt_string& file_name,
860               int line_number)
861  {
862  }
863};
864
865class KwdDefault : public Kwd
866{
867public:
868  void action (const CmtSystem::cmt_string_vector& words,
869               Use* use,
870               const cmt_string& file_name,
871               int line_number)
872  {
873    /*
874      Unknown keyword : just ignore the line
875    */
876    if (!Cmt::get_quiet ())
877      {
878        cerr << "#CMT> bad syntax in requirements of " << use->get_package_name ()
879             << " " << use->version << " line #" << line_number;
880        cerr << " [" << words[0] << "...]" << endl;
881      }
882   
883    CmtError::set (CmtError::syntax_error, "ParseRequirements> ");
884  }
885};
886
887SyntaxParser& SyntaxParser::instance ()
888{
889  static SyntaxParser p;
890
891  return (p);
892}
893
894/**
895 *  Parse the input file, rejecting comments and
896 * rebuilding complete lines (from sections separated by
897 *  \ characters.
898 *
899 *  Each reformatted line is parsed by filter_line
900 */
901void SyntaxParser::parse_requirements (const cmt_string& file_name, Use* use)
902{
903  SyntaxParser& me = instance ();
904
905  if (use != 0)
906    {
907      cmt_string buffer;
908
909      use->fill_standard_macros (buffer);
910
911      AccessMode saved_current_access = Cmt::get_current_access ();
912      Cmt::set_current_access (UserMode);
913      me.do_parse_text (buffer, "", package_context, use, 0);
914      Cmt::set_current_access (saved_current_access);
915    }
916
917  me.do_parse_requirements (file_name, use);
918
919  if (use != 0)
920    {
921      use->close_scope_sections ();
922    }
923}
924
925/**
926 */
927void SyntaxParser::parse_project_file_text (const cmt_string& text,
928                                            const cmt_string& file_name,
929                                            Project* project)
930{
931  SyntaxParser& me = instance ();
932  me.do_parse_text (text, file_name, project_context, 0, project);
933}
934
935/**
936 *  Parse a text, rejecting comments and
937 * rebuilding complete lines (from sections separated by
938 *  \ characters.
939 *
940 *  Each reformatted line is parsed by filter_line
941 */
942void SyntaxParser::parse_requirements_text (const cmt_string& text,
943                                            const cmt_string& file_name,
944                                            Use* use)
945{
946  SyntaxParser& me = instance ();
947
948    /**
949     *
950     *    We have to preserve m_current_access since it reflects whether
951     *   the current cmt action is run in the context of the current package.
952     *   (the opposite is when the cmt command specifies the current package
953     *    in its arguments -use=... therefore the pwd is NOT the directory
954     *    of the current package)
955     *
956     *   m_current_access is Developer when pwd =  current
957     *                       User      when pwd != current
958     *
959     *    Therefore, as soon as we reach a used package, this must be switched to User
960     *
961     *   On the other hand, Cmt::scope reflects the status of the public/private
962     *  statements. By default, we are in public context when entering a new requirements
963     *  file.
964     *
965     */
966
967  AccessMode saved_current_access;
968
969  saved_current_access = Cmt::get_current_access ();
970
971  if (use == 0) use = &(Use::current ());
972
973  if (use != &(Use::current ()))
974    {
975      if (Cmt::get_debug ())
976        {
977          cout << "parse_requirements_text> set UserMode" << endl;
978        }
979
980      Cmt::set_current_access (UserMode);
981    }
982  else
983    {
984      if (Cmt::get_debug ())
985        {
986          cout << "parse_requirements_text> set DeveloperMode" << endl;
987        }
988
989      Cmt::set_current_access (DeveloperMode);
990    }
991
992  me.do_parse_text (text, file_name, package_context, use, 0);
993
994  Cmt::set_current_access (saved_current_access);
995}
996
997/**
998 *  Apply the basic parser to one single line :
999 *
1000 *   o Append to global text if previous back_slash
1001 *   o Split into words
1002 *   o Apply the generic Select operator
1003 */
1004void SyntaxParser::parse_requirements_line (const cmt_string& line,
1005                                            Use* use,
1006                                            const cmt_string& file_name,
1007                                            int line_number)
1008{
1009  SyntaxParser& me = instance ();
1010  me.do_parse_line (line, file_name, line_number, package_context, use, 0);
1011}
1012
1013SyntaxParser::SyntaxParser ()
1014{
1015  m_keywords.add ("action", new KwdAction ());
1016  m_keywords.add ("alias", new KwdAlias ());
1017  m_keywords.add ("application", new KwdApplication ());
1018  m_keywords.add ("apply_pattern", new KwdApplyPattern ());
1019  m_keywords.add ("apply_tag", new KwdApplyTag ());
1020  m_keywords.add ("author", new KwdAuthor ());
1021  m_keywords.add ("branches", new KwdBranches ());
1022  m_keywords.add ("build_strategy", new KwdBuildStrategy ());
1023  m_keywords.add ("cleanup_script", new KwdCleanupScript ());
1024  m_keywords.add ("cmtpath_pattern", new KwdCmtPathPattern ());
1025  m_keywords.add ("document", new KwdDocument ());
1026  m_keywords.add ("end_private", new KwdEndPrivate ());
1027  m_keywords.add ("end_public", new KwdEndPublic ());
1028  m_keywords.add ("ignore_pattern", new KwdIgnorePattern ());
1029  m_keywords.add ("include_dirs", new KwdIncludeDirs ());
1030  m_keywords.add ("include_path", new KwdIncludePath ());
1031  m_keywords.add ("language", new KwdLanguage ());
1032  m_keywords.add ("library", new KwdLibrary ());
1033  m_keywords.add ("macro", new KwdMacro ());
1034  m_keywords.add ("macro+", new KwdMacroAppend ());
1035  m_keywords.add ("macro_prepend", new KwdMacroPrepend ());
1036  m_keywords.add ("macro_append", new KwdMacroAppend ());
1037  m_keywords.add ("macro_remove", new KwdMacroRemove ());
1038  m_keywords.add ("macro_remove_regexp", new KwdMacroRemoveRegexp ());
1039  m_keywords.add ("macro_remove_all", new KwdMacroRemoveAll ());
1040  m_keywords.add ("macro_remove_all_regexp", new KwdMacroRemoveAllRegexp ());
1041  m_keywords.add ("make_fragment", new KwdMakeFragment ());
1042  m_keywords.add ("manager", new KwdManager ());
1043  m_keywords.add ("package", new KwdPackage ());
1044  m_keywords.add ("path", new KwdPath ());
1045  m_keywords.add ("path_append", new KwdPathAppend ());
1046  m_keywords.add ("path_prepend", new KwdPathPrepend ());
1047  m_keywords.add ("path_remove", new KwdPathRemove ());
1048  m_keywords.add ("path_remove_regexp", new KwdPathRemoveRegexp ());
1049  m_keywords.add ("pattern", new KwdPattern ());
1050  m_keywords.add ("public", new KwdPublic ());
1051  m_keywords.add ("private", new KwdPrivate ());
1052  m_keywords.add ("project", new KwdProject ());
1053  m_keywords.add ("set", new KwdSet ());
1054  m_keywords.add ("set_append", new KwdSetAppend ());
1055  m_keywords.add ("set_prepend", new KwdSetPrepend ());
1056  m_keywords.add ("set_remove", new KwdSetRemove ());
1057  m_keywords.add ("set_remove_regexp", new KwdSetRemoveRegexp ());
1058  m_keywords.add ("setup_script", new KwdSetupScript ());
1059  m_keywords.add ("setup_strategy", new KwdSetupStrategy ());
1060  m_keywords.add ("tag", new KwdTag ());
1061  m_keywords.add ("tag_exclude", new KwdTagExclude ());
1062  m_keywords.add ("use", new KwdUse ());
1063  m_keywords.add ("version_strategy", new KwdVersionStrategy ());
1064  m_keywords.add ("version", new KwdVersion ());
1065
1066  m_project_keywords.add ("build_strategy", new KwdBuildStrategy ());
1067  m_project_keywords.add ("project", new KwdProject ());
1068  m_project_keywords.add ("setup_strategy", new KwdSetupStrategy ());
1069  m_project_keywords.add ("use", new KwdUse ());
1070}
1071
1072void SyntaxParser::do_parse_requirements (const cmt_string& file_name, Use* use)
1073{
1074  cmt_string actual_file_name = file_name;
1075  cmt_string text;
1076
1077  CmtError::clear ();
1078
1079  if (!CmtSystem::test_file (actual_file_name))
1080    {
1081      actual_file_name = "..";
1082      actual_file_name += CmtSystem::file_separator ();
1083      actual_file_name += "cmt";
1084      actual_file_name += CmtSystem::file_separator ();
1085      actual_file_name += file_name;
1086
1087      if (!CmtSystem::test_file (actual_file_name))
1088        {
1089          actual_file_name = "..";
1090          actual_file_name += CmtSystem::file_separator ();
1091          actual_file_name += "mgr";
1092          actual_file_name += CmtSystem::file_separator ();
1093          actual_file_name += file_name;
1094
1095          if (!CmtSystem::test_file (actual_file_name))
1096            {
1097              return;
1098            }
1099        }
1100    }
1101
1102  text.read (actual_file_name);
1103
1104  SyntaxParser::parse_requirements_text (text, actual_file_name, use);
1105}
1106
1107/**
1108 *  Parse a text, rejecting comments and
1109 * rebuilding complete lines (from sections separated by
1110 *  \ characters.
1111 *
1112 *  Each reformatted line is parsed by filter_line
1113 */
1114void SyntaxParser::do_parse_text (const cmt_string& text,
1115                                  const cmt_string& file_name,
1116                                  ContextType context,
1117                                  Use* use,
1118                                  Project* project)
1119{
1120  cmt_string line;
1121  int pos;
1122  int max_pos;
1123  int line_number = 1;
1124
1125  if (context == package_context)
1126    {
1127      if (use == 0) use = &(Use::current ());
1128    }
1129
1130  m_filtered_text.erase (0);
1131
1132  pos = 0;
1133  max_pos = text.size ();
1134
1135  for (pos = 0; pos < max_pos;)
1136    {
1137      int cr = text.find (pos, "\r\n");
1138      int nl = text.find (pos, '\n');
1139      int first = nl;
1140      int length = 1;
1141
1142      if (cr != cmt_string::npos)
1143        {
1144          if (nl == cmt_string::npos)
1145            {
1146              first = cr;
1147              length = 2;
1148            }
1149          else
1150            {
1151              first = (nl < cr) ? nl : cr;
1152              length = (nl < cr) ? 1 : 2;
1153            }
1154        }
1155
1156      if (first == cmt_string::npos)
1157        {
1158          text.substr (pos, line);
1159          pos = max_pos;
1160        }
1161      else if (first > pos)
1162        {
1163          text.substr (pos, first - pos, line);
1164          pos = first + length;
1165        }
1166      else
1167        {
1168          line.erase (0);
1169          pos += length;
1170        }
1171
1172      do_parse_line (line, file_name, line_number, context, use, project);
1173
1174      if ((Cmt::get_action () == action_check_configuration) && CmtError::has_pending_error ())
1175        {
1176          //break;
1177        }
1178
1179      line_number++;
1180    }
1181}
1182
1183void SyntaxParser::do_parse_line (const cmt_string& line,
1184                                  const cmt_string& file_name,
1185                                  int line_number,
1186                                  ContextType context,
1187                                  Use* use,
1188                                  Project* project)
1189{
1190  int length;
1191  int nl;
1192  int back_slash;
1193  cmt_string temp_line = line;
1194
1195  if (temp_line.size () == 0) return;
1196  if (temp_line[0] == '#') return;
1197
1198  nl = temp_line.find_last_of ('\n');
1199  if (nl != cmt_string::npos) temp_line.erase (nl);
1200
1201  length = temp_line.size ();
1202  if (length == 0) return;
1203
1204  //
1205  // We scan the line for handling backslashes.
1206  //
1207  // o Really terminating backslashes (ie those only followed by spaces/tabs
1208  // mean continued line
1209  //
1210  //
1211
1212  bool finished = true;
1213
1214  length = temp_line.size ();
1215
1216  back_slash = temp_line.find_last_of ('\\');
1217
1218  if (back_slash != cmt_string::npos)
1219    {
1220      //
1221      // This is the last backslash
1222      // check if there are only space chars after it
1223      //
1224     
1225      bool at_end = true;
1226
1227      for (int i = (back_slash + 1); i < length; i++)
1228        {
1229          char c = temp_line[i];
1230          if ((c != ' ') && (c != '\t'))
1231            {
1232              at_end = false;
1233              break;
1234            }
1235        }
1236
1237      if (at_end)
1238        {
1239          temp_line.erase (back_slash);
1240          finished = false;
1241        }
1242      else
1243        {
1244          // This was not a trailing backslash.
1245          finished = true;
1246        }
1247    }
1248
1249  m_filtered_text += temp_line;
1250
1251  if (!finished)
1252    {
1253      // We still need to accumulate forthcoming lines
1254      // before parsing the resulting text.
1255      return;
1256    }
1257
1258  /*
1259    Here a full line (possibly accumulating several lines
1260    ended by backslashes) is parsed :
1261   
1262    o Special characters are filtered now :
1263   
1264    <cmt:tab/>  \t
1265    <cmt:cr/>   \r
1266    <cmt:lf/>   \n
1267   
1268    o Split into words (a word is a string not containing
1269    spaces or enclosed in quotes)
1270
1271    o Parse the word array (function Select)
1272
1273  */
1274
1275  m_filtered_text.replace_all ("<cmt:tab/>", "\t");
1276  m_filtered_text.replace_all ("<cmt:cr/>",  "\r");
1277  m_filtered_text.replace_all ("<cmt:lf/>",  "\n");
1278
1279  if (Cmt::get_debug ())
1280    {
1281      cout << "parse_requirements_line [" << m_filtered_text << "]" << endl;
1282    }
1283 
1284  static CmtSystem::cmt_string_vector words;
1285 
1286  CmtSystem::split (m_filtered_text, " \t", words);
1287 
1288  if (words.size () != 0)
1289    {
1290      switch (context)
1291        {
1292        case project_context:
1293          do_parse_words (words, file_name, line_number, project);
1294          break;
1295        case package_context:
1296          do_parse_words (words, file_name, line_number, use);
1297          break;
1298        }
1299    }
1300 
1301  m_filtered_text.erase (0);
1302}
1303
1304void SyntaxParser::do_parse_words (const CmtSystem::cmt_string_vector& words,
1305                                   const cmt_string& file_name,
1306                                   int line_number,
1307                                   Use* use)
1308{
1309  CmtError::clear ();
1310
1311  if (words.size () == 0) return;
1312
1313  const cmt_string& command = words[0];
1314
1315  if (command.size () == 0) return;
1316
1317  //
1318  // First analyze the syntax
1319  //
1320
1321  Kwd* keyword = m_keywords.find (command);
1322  if (keyword == 0)
1323    {
1324      /*
1325
1326        When the first word of the line is not a keyword, it may be an
1327        implicit pattern application.
1328
1329       */
1330
1331      Pattern* p = Pattern::find (command);
1332      if (p == 0)
1333        {
1334          CmtError::set (CmtError::syntax_error, "ParseRequirements> ");
1335        }
1336      else
1337        {
1338          keyword = m_keywords.find ("apply_pattern");
1339        }
1340    }
1341
1342  if (CmtError::has_pending_error ())
1343    {
1344      if (!Cmt::get_quiet ())
1345        {
1346          cerr << "#CMT> bad syntax in requirements of " << use->get_package_name ()
1347               << " " << use->version
1348               << " " << use->specified_path
1349               << " line #" << line_number;
1350          cerr << " [" << command << " ...]" << endl;
1351        }
1352
1353      return;
1354    }
1355
1356  //
1357  // Then interpret the action
1358  //
1359
1360  keyword->action (words, use, file_name, line_number);
1361}
1362
1363void SyntaxParser::do_parse_words (const CmtSystem::cmt_string_vector& words,
1364                                   const cmt_string& file_name,
1365                                   int line_number,
1366                                   Project* project)
1367{
1368  CmtError::clear ();
1369
1370  if (words.size () == 0) return;
1371
1372  const cmt_string& command = words[0];
1373
1374  if (command.size () == 0) return;
1375
1376  //
1377  // First analyze the syntax
1378  //
1379
1380  Kwd* keyword = m_project_keywords.find (command);
1381  if (keyword == 0)
1382    {
1383      CmtError::set (CmtError::syntax_error, "ParseRequirements> ");
1384    }
1385
1386  if (CmtError::has_pending_error ())
1387    {
1388      if (!Cmt::get_quiet ())
1389        {
1390          cerr << "#CMT> bad syntax in project file of " << project->get_name ()
1391               << " line #" << line_number;
1392          cerr << " [" << command << " ...]" << endl;
1393        }
1394
1395      return;
1396    }
1397
1398  //
1399  // Then interpret the action
1400  //
1401
1402  keyword->action (words, project, file_name, line_number);
1403}
1404
1405
1406
1407
Note: See TracBrowser for help on using the repository browser.